diff --git a/generators/php.js b/generators/php.js index 479a53e77..df90cdc20 100644 --- a/generators/php.js +++ b/generators/php.js @@ -15,287 +15,302 @@ goog.declareModuleId('Blockly.PHP'); import * as stringUtils from '../core/utils/string.js'; // import type {Block} from '../core/block.js'; import {CodeGenerator} from '../core/generator.js'; -import {inputTypes} from '../core/inputs/input_types.js'; import {Names} from '../core/names.js'; // import type {Workspace} from '../core/workspace.js'; +import {inputTypes} from '../core/inputs/input_types.js'; -/** - * PHP code generator. - * @type {!CodeGenerator} - */ -const PHP = new CodeGenerator('PHP'); - -/** - * 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. - */ -PHP.addReservedWords( - // http://php.net/manual/en/reserved.keywords.php - '__halt_compiler,abstract,and,array,as,break,callable,case,catch,class,' + - 'clone,const,continue,declare,default,die,do,echo,else,elseif,empty,' + - 'enddeclare,endfor,endforeach,endif,endswitch,endwhile,eval,exit,extends,' + - 'final,for,foreach,function,global,goto,if,implements,include,' + - 'include_once,instanceof,insteadof,interface,isset,list,namespace,new,or,' + - 'print,private,protected,public,require,require_once,return,static,' + - 'switch,throw,trait,try,unset,use,var,while,xor,' + - // http://php.net/manual/en/reserved.constants.php - 'PHP_VERSION,PHP_MAJOR_VERSION,PHP_MINOR_VERSION,PHP_RELEASE_VERSION,' + - 'PHP_VERSION_ID,PHP_EXTRA_VERSION,PHP_ZTS,PHP_DEBUG,PHP_MAXPATHLEN,' + - 'PHP_OS,PHP_SAPI,PHP_EOL,PHP_INT_MAX,PHP_INT_SIZE,DEFAULT_INCLUDE_PATH,' + - 'PEAR_INSTALL_DIR,PEAR_EXTENSION_DIR,PHP_EXTENSION_DIR,PHP_PREFIX,' + - 'PHP_BINDIR,PHP_BINARY,PHP_MANDIR,PHP_LIBDIR,PHP_DATADIR,PHP_SYSCONFDIR,' + - 'PHP_LOCALSTATEDIR,PHP_CONFIG_FILE_PATH,PHP_CONFIG_FILE_SCAN_DIR,' + - 'PHP_SHLIB_SUFFIX,E_ERROR,E_WARNING,E_PARSE,E_NOTICE,E_CORE_ERROR,' + - 'E_CORE_WARNING,E_COMPILE_ERROR,E_COMPILE_WARNING,E_USER_ERROR,' + - 'E_USER_WARNING,E_USER_NOTICE,E_DEPRECATED,E_USER_DEPRECATED,E_ALL,' + - 'E_STRICT,__COMPILER_HALT_OFFSET__,TRUE,FALSE,NULL,__CLASS__,__DIR__,' + - '__FILE__,__FUNCTION__,__LINE__,__METHOD__,__NAMESPACE__,__TRAIT__'); - /** * Order of operation ENUMs. * http://php.net/manual/en/language.operators.precedence.php + * @enum {number} */ -PHP.ORDER_ATOMIC = 0; // 0 "" ... -PHP.ORDER_CLONE = 1; // clone -PHP.ORDER_NEW = 1; // new -PHP.ORDER_MEMBER = 2.1; // [] -PHP.ORDER_FUNCTION_CALL = 2.2; // () -PHP.ORDER_POWER = 3; // ** -PHP.ORDER_INCREMENT = 4; // ++ -PHP.ORDER_DECREMENT = 4; // -- -PHP.ORDER_BITWISE_NOT = 4; // ~ -PHP.ORDER_CAST = 4; // (int) (float) (string) (array) ... -PHP.ORDER_SUPPRESS_ERROR = 4; // @ -PHP.ORDER_INSTANCEOF = 5; // instanceof -PHP.ORDER_LOGICAL_NOT = 6; // ! -PHP.ORDER_UNARY_PLUS = 7.1; // + -PHP.ORDER_UNARY_NEGATION = 7.2; // - -PHP.ORDER_MULTIPLICATION = 8.1; // * -PHP.ORDER_DIVISION = 8.2; // / -PHP.ORDER_MODULUS = 8.3; // % -PHP.ORDER_ADDITION = 9.1; // + -PHP.ORDER_SUBTRACTION = 9.2; // - -PHP.ORDER_STRING_CONCAT = 9.3; // . -PHP.ORDER_BITWISE_SHIFT = 10; // << >> -PHP.ORDER_RELATIONAL = 11; // < <= > >= -PHP.ORDER_EQUALITY = 12; // == != === !== <> <=> -PHP.ORDER_REFERENCE = 13; // & -PHP.ORDER_BITWISE_AND = 13; // & -PHP.ORDER_BITWISE_XOR = 14; // ^ -PHP.ORDER_BITWISE_OR = 15; // | -PHP.ORDER_LOGICAL_AND = 16; // && -PHP.ORDER_LOGICAL_OR = 17; // || -PHP.ORDER_IF_NULL = 18; // ?? -PHP.ORDER_CONDITIONAL = 19; // ?: -PHP.ORDER_ASSIGNMENT = 20; // = += -= *= /= %= <<= >>= ... -PHP.ORDER_LOGICAL_AND_WEAK = 21; // and -PHP.ORDER_LOGICAL_XOR = 22; // xor -PHP.ORDER_LOGICAL_OR_WEAK = 23; // or -PHP.ORDER_NONE = 99; // (...) +export const Order = { + ATOMIC: 0, // 0 "" ... + CLONE: 1, // clone + NEW: 1, // new + MEMBER: 2.1, // [] + FUNCTION_CALL: 2.2, // () + POWER: 3, // ** + INCREMENT: 4, // ++ + DECREMENT: 4, // -- + BITWISE_NOT: 4, // ~ + CAST: 4, // (int) (float) (string) (array) ... + SUPPRESS_ERROR: 4, // @ + INSTANCEOF: 5, // instanceof + LOGICAL_NOT: 6, // ! + UNARY_PLUS: 7.1, // + + UNARY_NEGATION: 7.2, // - + MULTIPLICATION: 8.1, // * + DIVISION: 8.2, // / + MODULUS: 8.3, // % + ADDITION: 9.1, // + + SUBTRACTION: 9.2, // - + STRING_CONCAT: 9.3, // . + BITWISE_SHIFT: 10, // << >> + RELATIONAL: 11, // < <= > >= + EQUALITY: 12, // == != === !== <> <=> + REFERENCE: 13, // & + BITWISE_AND: 13, // & + BITWISE_XOR: 14, // ^ + BITWISE_OR: 15, // | + LOGICAL_AND: 16, // && + LOGICAL_OR: 17, // || + IF_NULL: 18, // ?? + CONDITIONAL: 19, // ?: + ASSIGNMENT: 20, // = += -= *= /= %= <<= >>= ... + LOGICAL_AND_WEAK: 21, // and + LOGICAL_XOR: 22, // xor + LOGICAL_OR_WEAK: 23, // or + NONE: 99, // (...) +}; -/** - * List of outer-inner pairings that do NOT require parentheses. - * @type {!Array>} - */ -PHP.ORDER_OVERRIDES = [ - // (foo()).bar() -> foo().bar() - // (foo())[0] -> foo()[0] - [PHP.ORDER_MEMBER, PHP.ORDER_FUNCTION_CALL], - // (foo[0])[1] -> foo[0][1] - // (foo.bar).baz -> foo.bar.baz - [PHP.ORDER_MEMBER, PHP.ORDER_MEMBER], - // !(!foo) -> !!foo - [PHP.ORDER_LOGICAL_NOT, PHP.ORDER_LOGICAL_NOT], - // a * (b * c) -> a * b * c - [PHP.ORDER_MULTIPLICATION, PHP.ORDER_MULTIPLICATION], - // a + (b + c) -> a + b + c - [PHP.ORDER_ADDITION, PHP.ORDER_ADDITION], - // a && (b && c) -> a && b && c - [PHP.ORDER_LOGICAL_AND, PHP.ORDER_LOGICAL_AND], - // a || (b || c) -> a || b || c - [PHP.ORDER_LOGICAL_OR, PHP.ORDER_LOGICAL_OR] -]; +class PhpGenerator extends CodeGenerator { + /** + * List of outer-inner pairings that do NOT require parentheses. + * @type {!Array>} + */ + ORDER_OVERRIDES = [ + // (foo()).bar() -> foo().bar() + // (foo())[0] -> foo()[0] + [Order.MEMBER, Order.FUNCTION_CALL], + // (foo[0])[1] -> foo[0][1] + // (foo.bar).baz -> foo.bar.baz + [Order.MEMBER, Order.MEMBER], + // !(!foo) -> !!foo + [Order.LOGICAL_NOT, Order.LOGICAL_NOT], + // a * (b * c) -> a * b * c + [Order.MULTIPLICATION, Order.MULTIPLICATION], + // a + (b + c) -> a + b + c + [Order.ADDITION, Order.ADDITION], + // a && (b && c) -> a && b && c + [Order.LOGICAL_AND, Order.LOGICAL_AND], + // a || (b || c) -> a || b || c + [Order.LOGICAL_OR, Order.LOGICAL_OR] + ]; -/** - * Whether the init method has been called. - * @type {?boolean} - */ -PHP.isInitialized = false; + constructor(name) { + super(name ?? 'PHP'); + this.isInitialized = false; -/** - * Initialise the database of variable names. - * @param {!Workspace} workspace Workspace to generate code from. - */ -PHP.init = function(workspace) { - // Call Blockly.CodeGenerator's init. - Object.getPrototypeOf(this).init.call(this); + // 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]; + } - if (!this.nameDB_) { - this.nameDB_ = new Names(this.RESERVED_WORDS_, '$'); - } else { - this.nameDB_.reset(); + // 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( + // http://php.net/manual/en/reserved.keywords.php + '__halt_compiler,abstract,and,array,as,break,callable,case,catch,class,' + + 'clone,const,continue,declare,default,die,do,echo,else,elseif,empty,' + + 'enddeclare,endfor,endforeach,endif,endswitch,endwhile,eval,exit,' + + 'extends,final,for,foreach,function,global,goto,if,implements,include,' + + 'include_once,instanceof,insteadof,interface,isset,list,namespace,new,' + + 'or,print,private,protected,public,require,require_once,return,static,' + + 'switch,throw,trait,try,unset,use,var,while,xor,' + + // http://php.net/manual/en/reserved.constants.php + 'PHP_VERSION,PHP_MAJOR_VERSION,PHP_MINOR_VERSION,PHP_RELEASE_VERSION,' + + 'PHP_VERSION_ID,PHP_EXTRA_VERSION,PHP_ZTS,PHP_DEBUG,PHP_MAXPATHLEN,' + + 'PHP_OS,PHP_SAPI,PHP_EOL,PHP_INT_MAX,PHP_INT_SIZE,DEFAULT_INCLUDE_PATH,' + + 'PEAR_INSTALL_DIR,PEAR_EXTENSION_DIR,PHP_EXTENSION_DIR,PHP_PREFIX,' + + 'PHP_BINDIR,PHP_BINARY,PHP_MANDIR,PHP_LIBDIR,PHP_DATADIR,' + + 'PHP_SYSCONFDIR,PHP_LOCALSTATEDIR,PHP_CONFIG_FILE_PATH,' + + 'PHP_CONFIG_FILE_SCAN_DIR,PHP_SHLIB_SUFFIX,E_ERROR,E_WARNING,E_PARSE,' + + 'E_NOTICE,E_CORE_ERROR,E_CORE_WARNING,E_COMPILE_ERROR,' + + 'E_COMPILE_WARNING,E_USER_ERROR,E_USER_WARNING,E_USER_NOTICE,' + + 'E_DEPRECATED,E_USER_DEPRECATED,E_ALL,E_STRICT,' + + '__COMPILER_HALT_OFFSET__,TRUE,FALSE,NULL,__CLASS__,__DIR__,__FILE__,' + + '__FUNCTION__,__LINE__,__METHOD__,__NAMESPACE__,__TRAIT__' + ); } - this.nameDB_.setVariableMap(workspace.getVariableMap()); - this.nameDB_.populateVariables(workspace); - this.nameDB_.populateProcedures(workspace); + /** + * Initialise the database of variable names. + * @param {!Workspace} workspace Workspace to generate code from. + */ + init(workspace) { + super.init(workspace); - this.isInitialized = true; -}; - -/** - * Prepend the generated code with the variable definitions. - * @param {string} code Generated code. - * @return {string} Completed code. - */ -PHP.finish = function(code) { - // Convert the definitions dictionary into a list. - const definitions = Object.values(this.definitions_); - // Call Blockly.CodeGenerator's finish. - code = Object.getPrototypeOf(this).finish.call(this, code); - this.isInitialized = false; - - this.nameDB_.reset(); - return definitions.join('\n\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. - */ -PHP.scrubNakedValue = function(line) { - return line + ';\n'; -}; - -/** - * Encode a string as a properly escaped PHP string, complete with - * quotes. - * @param {string} string Text to encode. - * @return {string} PHP string. - * @protected - */ -PHP.quote_ = function(string) { - string = string.replace(/\\/g, '\\\\') - .replace(/\n/g, '\\\n') - .replace(/'/g, '\\\''); - return '\'' + string + '\''; -}; - -/** - * Encode a string as a properly escaped multiline PHP string, complete with - * quotes. - * @param {string} string Text to encode. - * @return {string} PHP string. - * @protected - */ -PHP.multiline_quote_ = function(string) { - const lines = string.split(/\n/g).map(this.quote_); - // Join with the following, plus a newline: - // . "\n" . - // Newline escaping only works in double-quoted strings. - return lines.join(' . \"\\n\" .\n'); -}; - -/** - * Common tasks for generating PHP 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 PHP code created for this block. - * @param {boolean=} opt_thisOnly True to generate code for only this statement. - * @return {string} PHP code with comments and subsequent blocks added. - * @protected - */ -PHP.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); - commentCode += this.prefixLines(comment, '// ') + '\n'; + if (!this.nameDB_) { + this.nameDB_ = new Names(this.RESERVED_WORDS_, '$'); + } else { + this.nameDB_.reset(); } - // 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, '// '); + + this.nameDB_.setVariableMap(workspace.getVariableMap()); + this.nameDB_.populateVariables(workspace); + this.nameDB_.populateProcedures(workspace); + + this.isInitialized = true; + }; + + /** + * Prepend the generated code with the variable definitions. + * @param {string} code Generated code. + * @return {string} Completed code. + */ + finish(code) { + // Convert the definitions dictionary into a list. + const definitions = Object.values(this.definitions_); + // Call Blockly.CodeGenerator's finish. + code = super.finish(code); + this.isInitialized = false; + + this.nameDB_.reset(); + return definitions.join('\n\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 PHP string, complete with + * quotes. + * @param {string} string Text to encode. + * @return {string} PHP string. + * @protected + */ + quote_(string) { + string = string.replace(/\\/g, '\\\\') + .replace(/\n/g, '\\\n') + .replace(/'/g, '\\\''); + return '\'' + string + '\''; + }; + + /** + * Encode a string as a properly escaped multiline PHP string, complete with + * quotes. + * @param {string} string Text to encode. + * @return {string} PHP string. + * @protected + */ + multiline_quote_(string) { + const lines = string.split(/\n/g).map(this.quote_); + // Join with the following, plus a newline: + // . "\n" . + // Newline escaping only works in double-quoted strings. + return lines.join(' . \"\\n\" .\n'); + }; + + /** + * Common tasks for generating PHP 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 PHP code created for this block. + * @param {boolean=} opt_thisOnly True to generate code for only this + * statement. + * @return {string} PHP 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); + 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; -}; + 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} - */ -PHP.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--; - } - let defaultAtIndex = block.workspace.options.oneBasedIndex ? '1' : '0'; - let outerOrder = order; - let innerOrder; - if (delta > 0) { - outerOrder = this.ORDER_ADDITION; - innerOrder = this.ORDER_ADDITION; - } else if (delta < 0) { - outerOrder = this.ORDER_SUBTRACTION; - innerOrder = this.ORDER_SUBTRACTION; - } else if (opt_negate) { - outerOrder = this.ORDER_UNARY_NEGATION; - innerOrder = this.ORDER_UNARY_NEGATION; - } - let at = this.valueToCode(block, atId, outerOrder) || defaultAtIndex; - - if (stringUtils.isNumber(at)) { - // If the index is a naked number, adjust it right now. - at = Number(at) + 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. + let defaultAtIndex = block.workspace.options.oneBasedIndex ? '1' : '0'; + let outerOrder = order; + let innerOrder; if (delta > 0) { - at = at + ' + ' + delta; + outerOrder = this.ORDER_ADDITION; + innerOrder = this.ORDER_ADDITION; } else if (delta < 0) { - at = at + ' - ' + -delta; + outerOrder = this.ORDER_SUBTRACTION; + innerOrder = this.ORDER_SUBTRACTION; + } else if (opt_negate) { + outerOrder = this.ORDER_UNARY_NEGATION; + innerOrder = this.ORDER_UNARY_NEGATION; } - if (opt_negate) { - if (delta) { - at = '-(' + at + ')'; - } else { - at = '-' + at; + let at = this.valueToCode(block, atId, outerOrder) || defaultAtIndex; + + if (stringUtils.isNumber(at)) { + // If the index is a naked number, adjust it right now. + at = Number(at) + 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; -}; -export {PHP as phpGenerator}; + return at; + }; +} + +/** + * PHP code generator. + * @type {!PhpGenerator} + */ +export const phpGenerator = new PhpGenerator(); diff --git a/generators/php/colour.js b/generators/php/colour.js index 149675b93..bd8cf4cb3 100644 --- a/generators/php/colour.js +++ b/generators/php/colour.js @@ -11,33 +11,33 @@ import * as goog from '../../closure/goog/goog.js'; goog.declareModuleId('Blockly.PHP.colour'); -import {phpGenerator as PHP} from '../php.js'; +import {phpGenerator, Order} from '../php.js'; -PHP.forBlock['colour_picker'] = function(block) { +phpGenerator.forBlock['colour_picker'] = function(block) { // Colour picker. - const code = PHP.quote_(block.getFieldValue('COLOUR')); - return [code, PHP.ORDER_ATOMIC]; + const code = phpGenerator.quote_(block.getFieldValue('COLOUR')); + return [code, Order.ATOMIC]; }; -PHP.forBlock['colour_random'] = function(block) { +phpGenerator.forBlock['colour_random'] = function(block) { // Generate a random colour. - const functionName = PHP.provideFunction_('colour_random', ` -function ${PHP.FUNCTION_NAME_PLACEHOLDER_}() { + const functionName = phpGenerator.provideFunction_('colour_random', ` +function ${phpGenerator.FUNCTION_NAME_PLACEHOLDER_}() { return '#' . str_pad(dechex(mt_rand(0, 0xFFFFFF)), 6, '0', STR_PAD_LEFT); } `); const code = functionName + '()'; - return [code, PHP.ORDER_FUNCTION_CALL]; + return [code, Order.FUNCTION_CALL]; }; -PHP.forBlock['colour_rgb'] = function(block) { +phpGenerator.forBlock['colour_rgb'] = function(block) { // Compose a colour from RGB components expressed as percentages. - const red = PHP.valueToCode(block, 'RED', PHP.ORDER_NONE) || 0; - const green = PHP.valueToCode(block, 'GREEN', PHP.ORDER_NONE) || 0; - const blue = PHP.valueToCode(block, 'BLUE', PHP.ORDER_NONE) || 0; - const functionName = PHP.provideFunction_('colour_rgb', ` -function ${PHP.FUNCTION_NAME_PLACEHOLDER_}($r, $g, $b) { + const red = phpGenerator.valueToCode(block, 'RED', Order.NONE) || 0; + const green = phpGenerator.valueToCode(block, 'GREEN', Order.NONE) || 0; + const blue = phpGenerator.valueToCode(block, 'BLUE', Order.NONE) || 0; + const functionName = phpGenerator.provideFunction_('colour_rgb', ` +function ${phpGenerator.FUNCTION_NAME_PLACEHOLDER_}($r, $g, $b) { $r = round(max(min($r, 100), 0) * 2.55); $g = round(max(min($g, 100), 0) * 2.55); $b = round(max(min($b, 100), 0) * 2.55); @@ -49,16 +49,18 @@ function ${PHP.FUNCTION_NAME_PLACEHOLDER_}($r, $g, $b) { } `); const code = functionName + '(' + red + ', ' + green + ', ' + blue + ')'; - return [code, PHP.ORDER_FUNCTION_CALL]; + return [code, Order.FUNCTION_CALL]; }; -PHP.forBlock['colour_blend'] = function(block) { +phpGenerator.forBlock['colour_blend'] = function(block) { // Blend two colours together. - const c1 = PHP.valueToCode(block, 'COLOUR1', PHP.ORDER_NONE) || "'#000000'"; - const c2 = PHP.valueToCode(block, 'COLOUR2', PHP.ORDER_NONE) || "'#000000'"; - const ratio = PHP.valueToCode(block, 'RATIO', PHP.ORDER_NONE) || 0.5; - const functionName = PHP.provideFunction_('colour_blend', ` -function ${PHP.FUNCTION_NAME_PLACEHOLDER_}($c1, $c2, $ratio) { + const c1 = + phpGenerator.valueToCode(block, 'COLOUR1', Order.NONE) || "'#000000'"; + const c2 = + phpGenerator.valueToCode(block, 'COLOUR2', Order.NONE) || "'#000000'"; + const ratio = phpGenerator.valueToCode(block, 'RATIO', Order.NONE) || 0.5; + const functionName = phpGenerator.provideFunction_('colour_blend', ` +function ${phpGenerator.FUNCTION_NAME_PLACEHOLDER_}($c1, $c2, $ratio) { $ratio = max(min($ratio, 1), 0); $r1 = hexdec(substr($c1, 1, 2)); $g1 = hexdec(substr($c1, 3, 2)); @@ -77,5 +79,5 @@ function ${PHP.FUNCTION_NAME_PLACEHOLDER_}($c1, $c2, $ratio) { } `); const code = functionName + '(' + c1 + ', ' + c2 + ', ' + ratio + ')'; - return [code, PHP.ORDER_FUNCTION_CALL]; + return [code, Order.FUNCTION_CALL]; }; diff --git a/generators/php/lists.js b/generators/php/lists.js index c4d180a83..f1deb5d1f 100644 --- a/generators/php/lists.js +++ b/generators/php/lists.js @@ -20,31 +20,31 @@ */ import * as goog from '../../closure/goog/goog.js'; -goog.declareModuleId('Blockly.PHP.lists'); +goog.declareModuleId('Blockly.phpGenerator.lists'); import * as stringUtils from '../../core/utils/string.js'; import {NameType} from '../../core/names.js'; -import {phpGenerator as PHP} from '../php.js'; +import {phpGenerator, Order} from '../php.js'; -PHP.forBlock['lists_create_empty'] = function(block) { +phpGenerator.forBlock['lists_create_empty'] = function(block) { // Create an empty list. - return ['array()', PHP.ORDER_FUNCTION_CALL]; + return ['array()', Order.FUNCTION_CALL]; }; -PHP.forBlock['lists_create_with'] = function(block) { +phpGenerator.forBlock['lists_create_with'] = function(block) { // Create a list with any number of elements of any type. let code = new Array(block.itemCount_); for (let i = 0; i < block.itemCount_; i++) { - code[i] = PHP.valueToCode(block, 'ADD' + i, PHP.ORDER_NONE) || 'null'; + code[i] = phpGenerator.valueToCode(block, 'ADD' + i, Order.NONE) || 'null'; } code = 'array(' + code.join(', ') + ')'; - return [code, PHP.ORDER_FUNCTION_CALL]; + return [code, Order.FUNCTION_CALL]; }; -PHP.forBlock['lists_repeat'] = function(block) { +phpGenerator.forBlock['lists_repeat'] = function(block) { // Create a list with one element repeated. - const functionName = PHP.provideFunction_('lists_repeat', ` -function ${PHP.FUNCTION_NAME_PLACEHOLDER_}($value, $count) { + const functionName = phpGenerator.provideFunction_('lists_repeat', ` +function ${phpGenerator.FUNCTION_NAME_PLACEHOLDER_}($value, $count) { $array = array(); for ($index = 0; $index < $count; $index++) { $array[] = $value; @@ -52,16 +52,16 @@ function ${PHP.FUNCTION_NAME_PLACEHOLDER_}($value, $count) { return $array; } `); - const element = PHP.valueToCode(block, 'ITEM', PHP.ORDER_NONE) || 'null'; - const repeatCount = PHP.valueToCode(block, 'NUM', PHP.ORDER_NONE) || '0'; + const element = phpGenerator.valueToCode(block, 'ITEM', Order.NONE) || 'null'; + const repeatCount = phpGenerator.valueToCode(block, 'NUM', Order.NONE) || '0'; const code = functionName + '(' + element + ', ' + repeatCount + ')'; - return [code, PHP.ORDER_FUNCTION_CALL]; + return [code, Order.FUNCTION_CALL]; }; -PHP.forBlock['lists_length'] = function(block) { +phpGenerator.forBlock['lists_length'] = function(block) { // String or array length. - const functionName = PHP.provideFunction_('length', ` -function ${PHP.FUNCTION_NAME_PLACEHOLDER_}($value) { + const functionName = phpGenerator.provideFunction_('length', ` +function ${phpGenerator.FUNCTION_NAME_PLACEHOLDER_}($value) { if (is_string($value)) { return strlen($value); } else { @@ -69,21 +69,23 @@ function ${PHP.FUNCTION_NAME_PLACEHOLDER_}($value) { } } `); - const list = PHP.valueToCode(block, 'VALUE', PHP.ORDER_NONE) || "''"; - return [functionName + '(' + list + ')', PHP.ORDER_FUNCTION_CALL]; + const list = phpGenerator.valueToCode(block, 'VALUE', Order.NONE) || "''"; + return [functionName + '(' + list + ')', Order.FUNCTION_CALL]; }; -PHP.forBlock['lists_isEmpty'] = function(block) { +phpGenerator.forBlock['lists_isEmpty'] = function(block) { // Is the string null or array empty? const argument0 = - PHP.valueToCode(block, 'VALUE', PHP.ORDER_FUNCTION_CALL) || 'array()'; - return ['empty(' + argument0 + ')', PHP.ORDER_FUNCTION_CALL]; + phpGenerator.valueToCode(block, 'VALUE', Order.FUNCTION_CALL) + || 'array()'; + return ['empty(' + argument0 + ')', Order.FUNCTION_CALL]; }; -PHP.forBlock['lists_indexOf'] = function(block) { +phpGenerator.forBlock['lists_indexOf'] = function(block) { // Find an item in the list. - const argument0 = PHP.valueToCode(block, 'FIND', PHP.ORDER_NONE) || "''"; - const argument1 = PHP.valueToCode(block, 'VALUE', PHP.ORDER_MEMBER) || '[]'; + const argument0 = phpGenerator.valueToCode(block, 'FIND', Order.NONE) || "''"; + const argument1 = + phpGenerator.valueToCode(block, 'VALUE', Order.MEMBER) || '[]'; let errorIndex = ' -1'; let indexAdjustment = ''; if (block.workspace.options.oneBasedIndex) { @@ -93,8 +95,8 @@ PHP.forBlock['lists_indexOf'] = function(block) { let functionName; if (block.getFieldValue('END') === 'FIRST') { // indexOf - functionName = PHP.provideFunction_('indexOf', ` -function ${PHP.FUNCTION_NAME_PLACEHOLDER_}($haystack, $needle) { + functionName = phpGenerator.provideFunction_('indexOf', ` +function ${phpGenerator.FUNCTION_NAME_PLACEHOLDER_}($haystack, $needle) { for ($index = 0; $index < count($haystack); $index++) { if ($haystack[$index] == $needle) return $index${indexAdjustment}; } @@ -103,8 +105,8 @@ function ${PHP.FUNCTION_NAME_PLACEHOLDER_}($haystack, $needle) { `); } else { // lastIndexOf - functionName = PHP.provideFunction_('lastIndexOf', ` -function ${PHP.FUNCTION_NAME_PLACEHOLDER_}($haystack, $needle) { + functionName = phpGenerator.provideFunction_('lastIndexOf', ` +function ${phpGenerator.FUNCTION_NAME_PLACEHOLDER_}($haystack, $needle) { $last = ${errorIndex}; for ($index = 0; $index < count($haystack); $index++) { if ($haystack[$index] == $needle) $last = $index${indexAdjustment}; @@ -115,10 +117,10 @@ function ${PHP.FUNCTION_NAME_PLACEHOLDER_}($haystack, $needle) { } const code = functionName + '(' + argument1 + ', ' + argument0 + ')'; - return [code, PHP.ORDER_FUNCTION_CALL]; + return [code, Order.FUNCTION_CALL]; }; -PHP.forBlock['lists_getIndex'] = function(block) { +phpGenerator.forBlock['lists_getIndex'] = function(block) { // Get element at index. const mode = block.getFieldValue('MODE') || 'GET'; const where = block.getFieldValue('WHERE') || 'FROM_START'; @@ -126,52 +128,52 @@ PHP.forBlock['lists_getIndex'] = function(block) { case 'FIRST': if (mode === 'GET') { const list = - PHP.valueToCode(block, 'VALUE', PHP.ORDER_MEMBER) || 'array()'; + phpGenerator.valueToCode(block, 'VALUE', Order.MEMBER) || 'array()'; const code = list + '[0]'; - return [code, PHP.ORDER_MEMBER]; + return [code, Order.MEMBER]; } else if (mode === 'GET_REMOVE') { const list = - PHP.valueToCode(block, 'VALUE', PHP.ORDER_NONE) || 'array()'; + phpGenerator.valueToCode(block, 'VALUE', Order.NONE) || 'array()'; const code = 'array_shift(' + list + ')'; - return [code, PHP.ORDER_FUNCTION_CALL]; + return [code, Order.FUNCTION_CALL]; } else if (mode === 'REMOVE') { const list = - PHP.valueToCode(block, 'VALUE', PHP.ORDER_NONE) || 'array()'; + phpGenerator.valueToCode(block, 'VALUE', Order.NONE) || 'array()'; return 'array_shift(' + list + ');\n'; } break; case 'LAST': if (mode === 'GET') { const list = - PHP.valueToCode(block, 'VALUE', PHP.ORDER_NONE) || 'array()'; + phpGenerator.valueToCode(block, 'VALUE', Order.NONE) || 'array()'; const code = 'end(' + list + ')'; - return [code, PHP.ORDER_FUNCTION_CALL]; + return [code, Order.FUNCTION_CALL]; } else if (mode === 'GET_REMOVE') { const list = - PHP.valueToCode(block, 'VALUE', PHP.ORDER_NONE) || 'array()'; + phpGenerator.valueToCode(block, 'VALUE', Order.NONE) || 'array()'; const code = 'array_pop(' + list + ')'; - return [code, PHP.ORDER_FUNCTION_CALL]; + return [code, Order.FUNCTION_CALL]; } else if (mode === 'REMOVE') { const list = - PHP.valueToCode(block, 'VALUE', PHP.ORDER_NONE) || 'array()'; + phpGenerator.valueToCode(block, 'VALUE', Order.NONE) || 'array()'; return 'array_pop(' + list + ');\n'; } break; case 'FROM_START': { - const at = PHP.getAdjusted(block, 'AT'); + const at = phpGenerator.getAdjusted(block, 'AT'); if (mode === 'GET') { const list = - PHP.valueToCode(block, 'VALUE', PHP.ORDER_MEMBER) || 'array()'; + phpGenerator.valueToCode(block, 'VALUE', Order.MEMBER) || 'array()'; const code = list + '[' + at + ']'; - return [code, PHP.ORDER_MEMBER]; + return [code, Order.MEMBER]; } else if (mode === 'GET_REMOVE') { const list = - PHP.valueToCode(block, 'VALUE', PHP.ORDER_NONE) || 'array()'; + phpGenerator.valueToCode(block, 'VALUE', Order.NONE) || 'array()'; const code = 'array_splice(' + list + ', ' + at + ', 1)[0]'; - return [code, PHP.ORDER_FUNCTION_CALL]; + return [code, Order.FUNCTION_CALL]; } else if (mode === 'REMOVE') { const list = - PHP.valueToCode(block, 'VALUE', PHP.ORDER_NONE) || 'array()'; + phpGenerator.valueToCode(block, 'VALUE', Order.NONE) || 'array()'; return 'array_splice(' + list + ', ' + at + ', 1);\n'; } break; @@ -179,48 +181,51 @@ PHP.forBlock['lists_getIndex'] = function(block) { case 'FROM_END': if (mode === 'GET') { const list = - PHP.valueToCode(block, 'VALUE', PHP.ORDER_NONE) || 'array()'; - const at = PHP.getAdjusted(block, 'AT', 1, true); + phpGenerator.valueToCode(block, 'VALUE', Order.NONE) || 'array()'; + const at = phpGenerator.getAdjusted(block, 'AT', 1, true); const code = 'array_slice(' + list + ', ' + at + ', 1)[0]'; - return [code, PHP.ORDER_FUNCTION_CALL]; + return [code, Order.FUNCTION_CALL]; } else if (mode === 'GET_REMOVE' || mode === 'REMOVE') { const list = - PHP.valueToCode(block, 'VALUE', PHP.ORDER_NONE) || 'array()'; + phpGenerator.valueToCode(block, 'VALUE', Order.NONE) || 'array()'; const at = - PHP.getAdjusted(block, 'AT', 1, false, PHP.ORDER_SUBTRACTION); + phpGenerator.getAdjusted(block, 'AT', 1, false, Order.SUBTRACTION); const code = 'array_splice(' + list + ', count(' + list + ') - ' + at + ', 1)[0]'; if (mode === 'GET_REMOVE') { - return [code, PHP.ORDER_FUNCTION_CALL]; + return [code, Order.FUNCTION_CALL]; } else if (mode === 'REMOVE') { return code + ';\n'; } } break; case 'RANDOM': { - const list = PHP.valueToCode(block, 'VALUE', PHP.ORDER_NONE) || 'array()'; + const list = + phpGenerator.valueToCode(block, 'VALUE', Order.NONE) || 'array()'; if (mode === 'GET') { - const functionName = PHP.provideFunction_('lists_get_random_item', ` -function ${PHP.FUNCTION_NAME_PLACEHOLDER_}($list) { + const functionName = + phpGenerator.provideFunction_('lists_get_random_item', ` +function ${phpGenerator.FUNCTION_NAME_PLACEHOLDER_}($list) { return $list[rand(0,count($list)-1)]; } `); const code = functionName + '(' + list + ')'; - return [code, PHP.ORDER_FUNCTION_CALL]; + return [code, Order.FUNCTION_CALL]; } else if (mode === 'GET_REMOVE') { const functionName = - PHP.provideFunction_('lists_get_remove_random_item', ` -function ${PHP.FUNCTION_NAME_PLACEHOLDER_}(&$list) { + phpGenerator.provideFunction_('lists_get_remove_random_item', ` +function ${phpGenerator.FUNCTION_NAME_PLACEHOLDER_}(&$list) { $x = rand(0,count($list)-1); unset($list[$x]); return array_values($list); } `); const code = functionName + '(' + list + ')'; - return [code, PHP.ORDER_FUNCTION_CALL]; + return [code, Order.FUNCTION_CALL]; } else if (mode === 'REMOVE') { - const functionName = PHP.provideFunction_('lists_remove_random_item', ` -function ${PHP.FUNCTION_NAME_PLACEHOLDER_}(&$list) { + const functionName = + phpGenerator.provideFunction_('lists_remove_random_item', ` +function ${phpGenerator.FUNCTION_NAME_PLACEHOLDER_}(&$list) { unset($list[rand(0,count($list)-1)]); } `); @@ -232,12 +237,13 @@ function ${PHP.FUNCTION_NAME_PLACEHOLDER_}(&$list) { throw Error('Unhandled combination (lists_getIndex).'); }; -PHP.forBlock['lists_setIndex'] = function(block) { +phpGenerator.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'; - const value = PHP.valueToCode(block, 'TO', PHP.ORDER_ASSIGNMENT) || 'null'; + const value = + phpGenerator.valueToCode(block, 'TO', Order.ASSIGNMENT) || 'null'; // Cache non-trivial values to variables to prevent repeated look-ups. // Closure, which accesses and modifies 'list'. let cachedList; @@ -245,7 +251,8 @@ PHP.forBlock['lists_setIndex'] = function(block) { if (cachedList.match(/^\$\w+$/)) { return ''; } - const listVar = PHP.nameDB_.getDistinctName('tmp_list', NameType.VARIABLE); + const listVar = + phpGenerator.nameDB_.getDistinctName('tmp_list', NameType.VARIABLE); const code = listVar + ' = &' + cachedList + ';\n'; cachedList = listVar; return code; @@ -254,19 +261,21 @@ PHP.forBlock['lists_setIndex'] = function(block) { case 'FIRST': if (mode === 'SET') { const list = - PHP.valueToCode(block, 'LIST', PHP.ORDER_MEMBER) || 'array()'; + phpGenerator.valueToCode(block, 'LIST', Order.MEMBER) || 'array()'; return list + '[0] = ' + value + ';\n'; } else if (mode === 'INSERT') { const list = - PHP.valueToCode(block, 'LIST', PHP.ORDER_NONE) || 'array()'; + phpGenerator.valueToCode(block, 'LIST', Order.NONE) || 'array()'; return 'array_unshift(' + list + ', ' + value + ');\n'; } break; case 'LAST': { - const list = PHP.valueToCode(block, 'LIST', PHP.ORDER_NONE) || 'array()'; + const list = + phpGenerator.valueToCode(block, 'LIST', Order.NONE) || 'array()'; if (mode === 'SET') { - const functionName = PHP.provideFunction_('lists_set_last_item', ` -function ${PHP.FUNCTION_NAME_PLACEHOLDER_}(&$list, $value) { + const functionName = + phpGenerator.provideFunction_('lists_set_last_item', ` +function ${phpGenerator.FUNCTION_NAME_PLACEHOLDER_}(&$list, $value) { $list[count($list) - 1] = $value; } `); @@ -277,31 +286,34 @@ function ${PHP.FUNCTION_NAME_PLACEHOLDER_}(&$list, $value) { break; } case 'FROM_START': { - const at = PHP.getAdjusted(block, 'AT'); + const at = phpGenerator.getAdjusted(block, 'AT'); if (mode === 'SET') { const list = - PHP.valueToCode(block, 'LIST', PHP.ORDER_MEMBER) || 'array()'; + phpGenerator.valueToCode(block, 'LIST', Order.MEMBER) || 'array()'; return list + '[' + at + '] = ' + value + ';\n'; } else if (mode === 'INSERT') { const list = - PHP.valueToCode(block, 'LIST', PHP.ORDER_NONE) || 'array()'; + phpGenerator.valueToCode(block, 'LIST', Order.NONE) || 'array()'; return 'array_splice(' + list + ', ' + at + ', 0, ' + value + ');\n'; } break; } case 'FROM_END': { - const list = PHP.valueToCode(block, 'LIST', PHP.ORDER_NONE) || 'array()'; - const at = PHP.getAdjusted(block, 'AT', 1); + const list = + phpGenerator.valueToCode(block, 'LIST', Order.NONE) || 'array()'; + const at = phpGenerator.getAdjusted(block, 'AT', 1); if (mode === 'SET') { - const functionName = PHP.provideFunction_('lists_set_from_end', ` -function ${PHP.FUNCTION_NAME_PLACEHOLDER_}(&$list, $at, $value) { + const functionName = + phpGenerator.provideFunction_('lists_set_from_end', ` +function ${phpGenerator.FUNCTION_NAME_PLACEHOLDER_}(&$list, $at, $value) { $list[count($list) - $at] = $value; } `); return functionName + '(' + list + ', ' + at + ', ' + value + ');\n'; } else if (mode === 'INSERT') { - const functionName = PHP.provideFunction_('lists_insert_from_end', ` -function ${PHP.FUNCTION_NAME_PLACEHOLDER_}(&$list, $at, $value) { + const functionName = + phpGenerator.provideFunction_('lists_insert_from_end', ` +function ${phpGenerator.FUNCTION_NAME_PLACEHOLDER_}(&$list, $at, $value) { return array_splice($list, count($list) - $at, 0, $value); } `); @@ -311,10 +323,11 @@ function ${PHP.FUNCTION_NAME_PLACEHOLDER_}(&$list, $at, $value) { } case 'RANDOM': cachedList = - PHP.valueToCode(block, 'LIST', PHP.ORDER_REFERENCE) || 'array()'; + phpGenerator.valueToCode(block, 'LIST', Order.REFERENCE) || 'array()'; let code = cacheList(); const list = cachedList; - const xVar = PHP.nameDB_.getDistinctName('tmp_x', NameType.VARIABLE); + const xVar = + phpGenerator.nameDB_.getDistinctName('tmp_x', NameType.VARIABLE); code += xVar + ' = rand(0, count(' + list + ')-1);\n'; if (mode === 'SET') { code += list + '[' + xVar + '] = ' + value + ';\n'; @@ -328,9 +341,9 @@ function ${PHP.FUNCTION_NAME_PLACEHOLDER_}(&$list, $at, $value) { throw Error('Unhandled combination (lists_setIndex).'); }; -PHP.forBlock['lists_getSublist'] = function(block) { +phpGenerator.forBlock['lists_getSublist'] = function(block) { // Get sublist. - const list = PHP.valueToCode(block, 'LIST', PHP.ORDER_NONE) || 'array()'; + const list = phpGenerator.valueToCode(block, 'LIST', Order.NONE) || 'array()'; const where1 = block.getFieldValue('WHERE1'); const where2 = block.getFieldValue('WHERE2'); let code; @@ -344,10 +357,11 @@ PHP.forBlock['lists_getSublist'] = function(block) { let at1; switch (where1) { case 'FROM_START': - at1 = PHP.getAdjusted(block, 'AT1'); + at1 = phpGenerator.getAdjusted(block, 'AT1'); break; case 'FROM_END': - at1 = PHP.getAdjusted(block, 'AT1', 1, false, PHP.ORDER_SUBTRACTION); + at1 = + phpGenerator.getAdjusted(block, 'AT1', 1, false, Order.SUBTRACTION); at1 = 'count(' + list + ') - ' + at1; break; case 'FIRST': @@ -360,7 +374,8 @@ PHP.forBlock['lists_getSublist'] = function(block) { let length; switch (where2) { case 'FROM_START': - at2 = PHP.getAdjusted(block, 'AT2', 0, false, PHP.ORDER_SUBTRACTION); + at2 = + phpGenerator.getAdjusted(block, 'AT2', 0, false, Order.SUBTRACTION); length = at2 + ' - '; if (stringUtils.isNumber(String(at1)) || String(at1).match(/^\(.+\)$/)) { @@ -371,7 +386,8 @@ PHP.forBlock['lists_getSublist'] = function(block) { length += ' + 1'; break; case 'FROM_END': - at2 = PHP.getAdjusted(block, 'AT2', 0, false, PHP.ORDER_SUBTRACTION); + at2 = + phpGenerator.getAdjusted(block, 'AT2', 0, false, Order.SUBTRACTION); length = 'count(' + list + ') - ' + at2 + ' - '; if (stringUtils.isNumber(String(at1)) || String(at1).match(/^\(.+\)$/)) { @@ -394,10 +410,11 @@ PHP.forBlock['lists_getSublist'] = function(block) { } code = 'array_slice(' + list + ', ' + at1 + ', ' + length + ')'; } else { - const at1 = PHP.getAdjusted(block, 'AT1'); - const at2 = PHP.getAdjusted(block, 'AT2'); - const functionName = PHP.provideFunction_('lists_get_sublist', ` -function ${PHP.FUNCTION_NAME_PLACEHOLDER_}($list, $where1, $at1, $where2, $at2) { + const at1 = phpGenerator.getAdjusted(block, 'AT1'); + const at2 = phpGenerator.getAdjusted(block, 'AT2'); + const functionName = + phpGenerator.provideFunction_('lists_get_sublist', ` +function ${phpGenerator.FUNCTION_NAME_PLACEHOLDER_}($list, $where1, $at1, $where2, $at2) { if ($where1 == 'FROM_END') { $at1 = count($list) - 1 - $at1; } else if ($where1 == 'FIRST') { @@ -421,16 +438,17 @@ function ${PHP.FUNCTION_NAME_PLACEHOLDER_}($list, $where1, $at1, $where2, $at2) code = functionName + '(' + list + ', \'' + where1 + '\', ' + at1 + ', \'' + where2 + '\', ' + at2 + ')'; } - return [code, PHP.ORDER_FUNCTION_CALL]; + return [code, Order.FUNCTION_CALL]; }; -PHP.forBlock['lists_sort'] = function(block) { +phpGenerator.forBlock['lists_sort'] = function(block) { // Block for sorting a list. - const listCode = PHP.valueToCode(block, 'LIST', PHP.ORDER_NONE) || 'array()'; + const listCode = + phpGenerator.valueToCode(block, 'LIST', Order.NONE) || 'array()'; const direction = block.getFieldValue('DIRECTION') === '1' ? 1 : -1; const type = block.getFieldValue('TYPE'); - const functionName = PHP.provideFunction_('lists_sort', ` -function ${PHP.FUNCTION_NAME_PLACEHOLDER_}($list, $type, $direction) { + const functionName = phpGenerator.provideFunction_('lists_sort', ` +function ${phpGenerator.FUNCTION_NAME_PLACEHOLDER_}($list, $type, $direction) { $sortCmpFuncs = array( 'NUMERIC' => 'strnatcasecmp', 'TEXT' => 'strcmp', @@ -447,13 +465,14 @@ function ${PHP.FUNCTION_NAME_PLACEHOLDER_}($list, $type, $direction) { `); const sortCode = functionName + '(' + listCode + ', "' + type + '", ' + direction + ')'; - return [sortCode, PHP.ORDER_FUNCTION_CALL]; + return [sortCode, Order.FUNCTION_CALL]; }; -PHP.forBlock['lists_split'] = function(block) { +phpGenerator.forBlock['lists_split'] = function(block) { // Block for splitting text into a list, or joining a list into text. - let value_input = PHP.valueToCode(block, 'INPUT', PHP.ORDER_NONE); - const value_delim = PHP.valueToCode(block, 'DELIM', PHP.ORDER_NONE) || "''"; + let value_input = phpGenerator.valueToCode(block, 'INPUT', Order.NONE); + const value_delim = + phpGenerator.valueToCode(block, 'DELIM', Order.NONE) || "''"; const mode = block.getFieldValue('MODE'); let functionName; if (mode === 'SPLIT') { @@ -470,12 +489,12 @@ PHP.forBlock['lists_split'] = function(block) { throw Error('Unknown mode: ' + mode); } const code = functionName + '(' + value_delim + ', ' + value_input + ')'; - return [code, PHP.ORDER_FUNCTION_CALL]; + return [code, Order.FUNCTION_CALL]; }; -PHP.forBlock['lists_reverse'] = function(block) { +phpGenerator.forBlock['lists_reverse'] = function(block) { // Block for reversing a list. - const list = PHP.valueToCode(block, 'LIST', PHP.ORDER_NONE) || '[]'; + const list = phpGenerator.valueToCode(block, 'LIST', Order.NONE) || '[]'; const code = 'array_reverse(' + list + ')'; - return [code, PHP.ORDER_FUNCTION_CALL]; + return [code, Order.FUNCTION_CALL]; }; diff --git a/generators/php/logic.js b/generators/php/logic.js index 7bd4c49a2..4ecdfe6c3 100644 --- a/generators/php/logic.js +++ b/generators/php/logic.js @@ -11,23 +11,26 @@ import * as goog from '../../closure/goog/goog.js'; goog.declareModuleId('Blockly.PHP.logic'); -import {phpGenerator as PHP} from '../php.js'; +import {phpGenerator, Order} from '../php.js'; -PHP.forBlock['controls_if'] = function(block) { +phpGenerator.forBlock['controls_if'] = function(block) { // If/elseif/else condition. let n = 0; let code = '', branchCode, conditionCode; - if (PHP.STATEMENT_PREFIX) { + if (phpGenerator.STATEMENT_PREFIX) { // Automatic prefix insertion is switched off for this block. Add manually. - code += PHP.injectId(PHP.STATEMENT_PREFIX, block); + code += phpGenerator.injectId(phpGenerator.STATEMENT_PREFIX, block); } do { - conditionCode = PHP.valueToCode(block, 'IF' + n, PHP.ORDER_NONE) || 'false'; - branchCode = PHP.statementToCode(block, 'DO' + n); - if (PHP.STATEMENT_SUFFIX) { - branchCode = PHP.prefixLines( - PHP.injectId(PHP.STATEMENT_SUFFIX, block), PHP.INDENT) + + conditionCode = + phpGenerator.valueToCode(block, 'IF' + n, Order.NONE) || 'false'; + branchCode = phpGenerator.statementToCode(block, 'DO' + n); + if (phpGenerator.STATEMENT_SUFFIX) { + branchCode = + phpGenerator.prefixLines( + phpGenerator.injectId(phpGenerator.STATEMENT_SUFFIX, block), + phpGenerator.INDENT) + branchCode; } code += (n > 0 ? ' else ' : '') + 'if (' + conditionCode + ') {\n' + @@ -35,11 +38,13 @@ PHP.forBlock['controls_if'] = function(block) { n++; } while (block.getInput('IF' + n)); - if (block.getInput('ELSE') || PHP.STATEMENT_SUFFIX) { - branchCode = PHP.statementToCode(block, 'ELSE'); - if (PHP.STATEMENT_SUFFIX) { - branchCode = PHP.prefixLines( - PHP.injectId(PHP.STATEMENT_SUFFIX, block), PHP.INDENT) + + if (block.getInput('ELSE') || phpGenerator.STATEMENT_SUFFIX) { + branchCode = phpGenerator.statementToCode(block, 'ELSE'); + if (phpGenerator.STATEMENT_SUFFIX) { + branchCode = + phpGenerator.prefixLines( + phpGenerator.injectId(phpGenerator.STATEMENT_SUFFIX, block), + phpGenerator.INDENT) + branchCode; } code += ' else {\n' + branchCode + '}'; @@ -47,28 +52,28 @@ PHP.forBlock['controls_if'] = function(block) { return code + '\n'; }; -PHP.forBlock['controls_ifelse'] = PHP.forBlock['controls_if']; +phpGenerator.forBlock['controls_ifelse'] = phpGenerator.forBlock['controls_if']; -PHP.forBlock['logic_compare'] = function(block) { +phpGenerator.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 === '!=') ? PHP.ORDER_EQUALITY : - PHP.ORDER_RELATIONAL; - const argument0 = PHP.valueToCode(block, 'A', order) || '0'; - const argument1 = PHP.valueToCode(block, 'B', order) || '0'; + const order = (operator === '==' || operator === '!=') ? Order.EQUALITY : + Order.RELATIONAL; + const argument0 = phpGenerator.valueToCode(block, 'A', order) || '0'; + const argument1 = phpGenerator.valueToCode(block, 'B', order) || '0'; const code = argument0 + ' ' + operator + ' ' + argument1; return [code, order]; }; -PHP.forBlock['logic_operation'] = function(block) { +phpGenerator.forBlock['logic_operation'] = function(block) { // Operations 'and', 'or'. const operator = (block.getFieldValue('OP') === 'AND') ? '&&' : '||'; const order = - (operator === '&&') ? PHP.ORDER_LOGICAL_AND : PHP.ORDER_LOGICAL_OR; - let argument0 = PHP.valueToCode(block, 'A', order); - let argument1 = PHP.valueToCode(block, 'B', order); + (operator === '&&') ? Order.LOGICAL_AND : Order.LOGICAL_OR; + let argument0 = phpGenerator.valueToCode(block, 'A', order); + let argument1 = phpGenerator.valueToCode(block, 'B', order); if (!argument0 && !argument1) { // If there are no arguments, then the return value is false. argument0 = 'false'; @@ -87,33 +92,33 @@ PHP.forBlock['logic_operation'] = function(block) { return [code, order]; }; -PHP.forBlock['logic_negate'] = function(block) { +phpGenerator.forBlock['logic_negate'] = function(block) { // Negation. - const order = PHP.ORDER_LOGICAL_NOT; - const argument0 = PHP.valueToCode(block, 'BOOL', order) || 'true'; + const order = Order.LOGICAL_NOT; + const argument0 = phpGenerator.valueToCode(block, 'BOOL', order) || 'true'; const code = '!' + argument0; return [code, order]; }; -PHP.forBlock['logic_boolean'] = function(block) { +phpGenerator.forBlock['logic_boolean'] = function(block) { // Boolean values true and false. const code = (block.getFieldValue('BOOL') === 'TRUE') ? 'true' : 'false'; - return [code, PHP.ORDER_ATOMIC]; + return [code, Order.ATOMIC]; }; -PHP.forBlock['logic_null'] = function(block) { +phpGenerator.forBlock['logic_null'] = function(block) { // Null data type. - return ['null', PHP.ORDER_ATOMIC]; + return ['null', Order.ATOMIC]; }; -PHP.forBlock['logic_ternary'] = function(block) { +phpGenerator.forBlock['logic_ternary'] = function(block) { // Ternary operator. const value_if = - PHP.valueToCode(block, 'IF', PHP.ORDER_CONDITIONAL) || 'false'; + phpGenerator.valueToCode(block, 'IF', Order.CONDITIONAL) || 'false'; const value_then = - PHP.valueToCode(block, 'THEN', PHP.ORDER_CONDITIONAL) || 'null'; + phpGenerator.valueToCode(block, 'THEN', Order.CONDITIONAL) || 'null'; const value_else = - PHP.valueToCode(block, 'ELSE', PHP.ORDER_CONDITIONAL) || 'null'; + phpGenerator.valueToCode(block, 'ELSE', Order.CONDITIONAL) || 'null'; const code = value_if + ' ? ' + value_then + ' : ' + value_else; - return [code, PHP.ORDER_CONDITIONAL]; + return [code, Order.CONDITIONAL]; }; diff --git a/generators/php/loops.js b/generators/php/loops.js index a1fc5bb2d..4448e7989 100644 --- a/generators/php/loops.js +++ b/generators/php/loops.js @@ -13,10 +13,10 @@ goog.declareModuleId('Blockly.PHP.loops'); import * as stringUtils from '../../core/utils/string.js'; import {NameType} from '../../core/names.js'; -import {phpGenerator as PHP} from '../php.js'; +import {phpGenerator, Order} from '../php.js'; -PHP.forBlock['controls_repeat_ext'] = function(block) { +phpGenerator.forBlock['controls_repeat_ext'] = function(block) { // Repeat n times. let repeats; if (block.getField('TIMES')) { @@ -24,15 +24,17 @@ PHP.forBlock['controls_repeat_ext'] = function(block) { repeats = String(Number(block.getFieldValue('TIMES'))); } else { // External number. - repeats = PHP.valueToCode(block, 'TIMES', PHP.ORDER_ASSIGNMENT) || '0'; + repeats = phpGenerator.valueToCode(block, 'TIMES', Order.ASSIGNMENT) || '0'; } - let branch = PHP.statementToCode(block, 'DO'); - branch = PHP.addLoopTrap(branch, block); + let branch = phpGenerator.statementToCode(block, 'DO'); + branch = phpGenerator.addLoopTrap(branch, block); let code = ''; - const loopVar = PHP.nameDB_.getDistinctName('count', NameType.VARIABLE); + const loopVar = + phpGenerator.nameDB_.getDistinctName('count', NameType.VARIABLE); let endVar = repeats; if (!repeats.match(/^\w+$/) && !stringUtils.isNumber(repeats)) { - endVar = PHP.nameDB_.getDistinctName('repeat_end', NameType.VARIABLE); + endVar = + phpGenerator.nameDB_.getDistinctName('repeat_end', NameType.VARIABLE); code += endVar + ' = ' + repeats + ';\n'; } code += 'for (' + loopVar + ' = 0; ' + loopVar + ' < ' + endVar + '; ' + @@ -40,32 +42,36 @@ PHP.forBlock['controls_repeat_ext'] = function(block) { return code; }; -PHP.forBlock['controls_repeat'] = PHP.forBlock['controls_repeat_ext']; +phpGenerator.forBlock['controls_repeat'] = + phpGenerator.forBlock['controls_repeat_ext']; -PHP.forBlock['controls_whileUntil'] = function(block) { +phpGenerator.forBlock['controls_whileUntil'] = function(block) { // Do while/until loop. const until = block.getFieldValue('MODE') === 'UNTIL'; let argument0 = - PHP.valueToCode( - block, 'BOOL', until ? PHP.ORDER_LOGICAL_NOT : PHP.ORDER_NONE) || + phpGenerator.valueToCode( + block, 'BOOL', until ? Order.LOGICAL_NOT : Order.NONE) || 'false'; - let branch = PHP.statementToCode(block, 'DO'); - branch = PHP.addLoopTrap(branch, block); + let branch = phpGenerator.statementToCode(block, 'DO'); + branch = phpGenerator.addLoopTrap(branch, block); if (until) { argument0 = '!' + argument0; } return 'while (' + argument0 + ') {\n' + branch + '}\n'; }; -PHP.forBlock['controls_for'] = function(block) { +phpGenerator.forBlock['controls_for'] = function(block) { // For loop. const variable0 = - PHP.nameDB_.getName(block.getFieldValue('VAR'), NameType.VARIABLE); - const argument0 = PHP.valueToCode(block, 'FROM', PHP.ORDER_ASSIGNMENT) || '0'; - const argument1 = PHP.valueToCode(block, 'TO', PHP.ORDER_ASSIGNMENT) || '0'; - const increment = PHP.valueToCode(block, 'BY', PHP.ORDER_ASSIGNMENT) || '1'; - let branch = PHP.statementToCode(block, 'DO'); - branch = PHP.addLoopTrap(branch, block); + phpGenerator.nameDB_.getName(block.getFieldValue('VAR'), NameType.VARIABLE); + const argument0 = + phpGenerator.valueToCode(block, 'FROM', Order.ASSIGNMENT) || '0'; + const argument1 = + phpGenerator.valueToCode(block, 'TO', Order.ASSIGNMENT) || '0'; + const increment = + phpGenerator.valueToCode(block, 'BY', Order.ASSIGNMENT) || '1'; + let branch = phpGenerator.statementToCode(block, 'DO'); + branch = phpGenerator.addLoopTrap(branch, block); let code; if (stringUtils.isNumber(argument0) && stringUtils.isNumber(argument1) && stringUtils.isNumber(increment)) { @@ -86,19 +92,22 @@ PHP.forBlock['controls_for'] = function(block) { let startVar = argument0; if (!argument0.match(/^\w+$/) && !stringUtils.isNumber(argument0)) { startVar = - PHP.nameDB_.getDistinctName(variable0 + '_start', NameType.VARIABLE); + phpGenerator.nameDB_.getDistinctName( + variable0 + '_start', NameType.VARIABLE); code += startVar + ' = ' + argument0 + ';\n'; } let endVar = argument1; if (!argument1.match(/^\w+$/) && !stringUtils.isNumber(argument1)) { endVar = - PHP.nameDB_.getDistinctName(variable0 + '_end', NameType.VARIABLE); + phpGenerator.nameDB_.getDistinctName( + variable0 + '_end', NameType.VARIABLE); code += endVar + ' = ' + argument1 + ';\n'; } // Determine loop direction at start, in case one of the bounds // changes during loop execution. const incVar = - PHP.nameDB_.getDistinctName(variable0 + '_inc', NameType.VARIABLE); + phpGenerator.nameDB_.getDistinctName( + variable0 + '_inc', NameType.VARIABLE); code += incVar + ' = '; if (stringUtils.isNumber(increment)) { code += Math.abs(increment) + ';\n'; @@ -106,7 +115,7 @@ PHP.forBlock['controls_for'] = function(block) { code += 'abs(' + increment + ');\n'; } code += 'if (' + startVar + ' > ' + endVar + ') {\n'; - code += PHP.INDENT + incVar + ' = -' + incVar + ';\n'; + code += phpGenerator.INDENT + incVar + ' = -' + incVar + ';\n'; code += '}\n'; code += 'for (' + variable0 + ' = ' + startVar + '; ' + incVar + ' >= 0 ? ' + variable0 + ' <= ' + endVar + ' : ' + variable0 + @@ -116,39 +125,40 @@ PHP.forBlock['controls_for'] = function(block) { return code; }; -PHP.forBlock['controls_forEach'] = function(block) { +phpGenerator.forBlock['controls_forEach'] = function(block) { // For each loop. const variable0 = - PHP.nameDB_.getName(block.getFieldValue('VAR'), NameType.VARIABLE); + phpGenerator.nameDB_.getName( + block.getFieldValue('VAR'), NameType.VARIABLE); const argument0 = - PHP.valueToCode(block, 'LIST', PHP.ORDER_ASSIGNMENT) || '[]'; - let branch = PHP.statementToCode(block, 'DO'); - branch = PHP.addLoopTrap(branch, block); + phpGenerator.valueToCode(block, 'LIST', Order.ASSIGNMENT) || '[]'; + let branch = phpGenerator.statementToCode(block, 'DO'); + branch = phpGenerator.addLoopTrap(branch, block); let code = ''; code += 'foreach (' + argument0 + ' as ' + variable0 + ') {\n' + branch + '}\n'; return code; }; -PHP.forBlock['controls_flow_statements'] = function(block) { +phpGenerator.forBlock['controls_flow_statements'] = function(block) { // Flow statements: continue, break. let xfix = ''; - if (PHP.STATEMENT_PREFIX) { + if (phpGenerator.STATEMENT_PREFIX) { // Automatic prefix insertion is switched off for this block. Add manually. - xfix += PHP.injectId(PHP.STATEMENT_PREFIX, block); + xfix += phpGenerator.injectId(phpGenerator.STATEMENT_PREFIX, block); } - if (PHP.STATEMENT_SUFFIX) { + if (phpGenerator.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 += PHP.injectId(PHP.STATEMENT_SUFFIX, block); + xfix += phpGenerator.injectId(phpGenerator.STATEMENT_SUFFIX, block); } - if (PHP.STATEMENT_PREFIX) { + if (phpGenerator.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 += PHP.injectId(PHP.STATEMENT_PREFIX, loop); + xfix += phpGenerator.injectId(phpGenerator.STATEMENT_PREFIX, loop); } } switch (block.getFieldValue('FLOW')) { diff --git a/generators/php/math.js b/generators/php/math.js index 6eb2d944f..b84571373 100644 --- a/generators/php/math.js +++ b/generators/php/math.js @@ -12,13 +12,13 @@ import * as goog from '../../closure/goog/goog.js'; goog.declareModuleId('Blockly.PHP.math'); import {NameType} from '../../core/names.js'; -import {phpGenerator as PHP} from '../php.js'; +import {phpGenerator, Order} from '../php.js'; -PHP.forBlock['math_number'] = function(block) { +phpGenerator.forBlock['math_number'] = function(block) { // Numeric value. let code = Number(block.getFieldValue('NUM')); - const order = code >= 0 ? PHP.ORDER_ATOMIC : PHP.ORDER_UNARY_NEGATION; + const order = code >= 0 ? Order.ATOMIC : Order.UNARY_NEGATION; if (code === Infinity) { code = 'INF'; } else if (code === -Infinity) { @@ -27,43 +27,43 @@ PHP.forBlock['math_number'] = function(block) { return [code, order]; }; -PHP.forBlock['math_arithmetic'] = function(block) { +phpGenerator.forBlock['math_arithmetic'] = function(block) { // Basic arithmetic operators, and power. const OPERATORS = { - 'ADD': [' + ', PHP.ORDER_ADDITION], - 'MINUS': [' - ', PHP.ORDER_SUBTRACTION], - 'MULTIPLY': [' * ', PHP.ORDER_MULTIPLICATION], - 'DIVIDE': [' / ', PHP.ORDER_DIVISION], - 'POWER': [' ** ', PHP.ORDER_POWER], + 'ADD': [' + ', Order.ADDITION], + 'MINUS': [' - ', Order.SUBTRACTION], + 'MULTIPLY': [' * ', Order.MULTIPLICATION], + 'DIVIDE': [' / ', Order.DIVISION], + 'POWER': [' ** ', Order.POWER], }; const tuple = OPERATORS[block.getFieldValue('OP')]; const operator = tuple[0]; const order = tuple[1]; - const argument0 = PHP.valueToCode(block, 'A', order) || '0'; - const argument1 = PHP.valueToCode(block, 'B', order) || '0'; + const argument0 = phpGenerator.valueToCode(block, 'A', order) || '0'; + const argument1 = phpGenerator.valueToCode(block, 'B', order) || '0'; const code = argument0 + operator + argument1; return [code, order]; }; -PHP.forBlock['math_single'] = function(block) { +phpGenerator.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 = PHP.valueToCode(block, 'NUM', PHP.ORDER_UNARY_NEGATION) || '0'; + arg = phpGenerator.valueToCode(block, 'NUM', Order.UNARY_NEGATION) || '0'; if (arg[0] === '-') { // --3 is not legal in JS. arg = ' ' + arg; } code = '-' + arg; - return [code, PHP.ORDER_UNARY_NEGATION]; + return [code, Order.UNARY_NEGATION]; } if (operator === 'SIN' || operator === 'COS' || operator === 'TAN') { - arg = PHP.valueToCode(block, 'NUM', PHP.ORDER_DIVISION) || '0'; + arg = phpGenerator.valueToCode(block, 'NUM', Order.DIVISION) || '0'; } else { - arg = PHP.valueToCode(block, 'NUM', PHP.ORDER_NONE) || '0'; + arg = phpGenerator.valueToCode(block, 'NUM', Order.NONE) || '0'; } // First, handle cases which generate values that don't need parentheses // wrapping the code. @@ -103,7 +103,7 @@ PHP.forBlock['math_single'] = function(block) { break; } if (code) { - return [code, PHP.ORDER_FUNCTION_CALL]; + return [code, Order.FUNCTION_CALL]; } // Second, handle cases which generate values that may need parentheses // wrapping the code. @@ -123,43 +123,44 @@ PHP.forBlock['math_single'] = function(block) { default: throw Error('Unknown math operator: ' + operator); } - return [code, PHP.ORDER_DIVISION]; + return [code, Order.DIVISION]; }; -PHP.forBlock['math_constant'] = function(block) { +phpGenerator.forBlock['math_constant'] = function(block) { // Constants: PI, E, the Golden Ratio, sqrt(2), 1/sqrt(2), INFINITY. const CONSTANTS = { - 'PI': ['M_PI', PHP.ORDER_ATOMIC], - 'E': ['M_E', PHP.ORDER_ATOMIC], - 'GOLDEN_RATIO': ['(1 + sqrt(5)) / 2', PHP.ORDER_DIVISION], - 'SQRT2': ['M_SQRT2', PHP.ORDER_ATOMIC], - 'SQRT1_2': ['M_SQRT1_2', PHP.ORDER_ATOMIC], - 'INFINITY': ['INF', PHP.ORDER_ATOMIC], + 'PI': ['M_PI', Order.ATOMIC], + 'E': ['M_E', Order.ATOMIC], + 'GOLDEN_RATIO': ['(1 + sqrt(5)) / 2', Order.DIVISION], + 'SQRT2': ['M_SQRT2', Order.ATOMIC], + 'SQRT1_2': ['M_SQRT1_2', Order.ATOMIC], + 'INFINITY': ['INF', Order.ATOMIC], }; return CONSTANTS[block.getFieldValue('CONSTANT')]; }; -PHP.forBlock['math_number_property'] = function(block) { +phpGenerator.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', PHP.ORDER_MODULUS, PHP.ORDER_EQUALITY], - 'ODD': ['', ' % 2 == 1', PHP.ORDER_MODULUS, PHP.ORDER_EQUALITY], - 'WHOLE': ['is_int(', ')', PHP.ORDER_NONE, PHP.ORDER_FUNCTION_CALL], - 'POSITIVE': ['', ' > 0', PHP.ORDER_RELATIONAL, PHP.ORDER_RELATIONAL], - 'NEGATIVE': ['', ' < 0', PHP.ORDER_RELATIONAL, PHP.ORDER_RELATIONAL], - 'DIVISIBLE_BY': [null, null, PHP.ORDER_MODULUS, PHP.ORDER_EQUALITY], - 'PRIME': [null, null, PHP.ORDER_NONE, PHP.ORDER_FUNCTION_CALL], + 'EVEN': ['', ' % 2 == 0', Order.MODULUS, Order.EQUALITY], + 'ODD': ['', ' % 2 == 1', Order.MODULUS, Order.EQUALITY], + 'WHOLE': ['is_int(', ')', Order.NONE, Order.FUNCTION_CALL], + 'POSITIVE': ['', ' > 0', Order.RELATIONAL, Order.RELATIONAL], + 'NEGATIVE': ['', ' < 0', Order.RELATIONAL, Order.RELATIONAL], + 'DIVISIBLE_BY': [null, null, Order.MODULUS, Order.EQUALITY], + 'PRIME': [null, null, Order.NONE, Order.FUNCTION_CALL], }; const dropdownProperty = block.getFieldValue('PROPERTY'); - const [prefix, suffix, inputOrder, outputOrder] = PROPERTIES[dropdownProperty]; - const numberToCheck = PHP.valueToCode(block, 'NUMBER_TO_CHECK', + const [prefix, suffix, inputOrder, outputOrder] = + PROPERTIES[dropdownProperty]; + const numberToCheck = phpGenerator.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. - const functionName = PHP.provideFunction_('math_isPrime', ` -function ${PHP.FUNCTION_NAME_PLACEHOLDER_}($n) { + const functionName = phpGenerator.provideFunction_('math_isPrime', ` +function ${phpGenerator.FUNCTION_NAME_PLACEHOLDER_}($n) { // https://en.wikipedia.org/wiki/Primality_test#Naive_methods if ($n == 2 || $n == 3) { return true; @@ -180,10 +181,10 @@ function ${PHP.FUNCTION_NAME_PLACEHOLDER_}($n) { `); code = functionName + '(' + numberToCheck + ')'; } else if (dropdownProperty === 'DIVISIBLE_BY') { - const divisor = PHP.valueToCode(block, 'DIVISOR', - PHP.ORDER_MODULUS) || '0'; + const divisor = phpGenerator.valueToCode(block, 'DIVISOR', + Order.MODULUS) || '0'; if (divisor === '0') { - return ['false', PHP.ORDER_ATOMIC]; + return ['false', Order.ATOMIC]; } code = numberToCheck + ' % ' + divisor + ' == 0'; @@ -193,20 +194,22 @@ function ${PHP.FUNCTION_NAME_PLACEHOLDER_}($n) { return [code, outputOrder]; }; -PHP.forBlock['math_change'] = function(block) { +phpGenerator.forBlock['math_change'] = function(block) { // Add to a variable in place. - const argument0 = PHP.valueToCode(block, 'DELTA', PHP.ORDER_ADDITION) || '0'; + const argument0 = + phpGenerator.valueToCode(block, 'DELTA', Order.ADDITION) || '0'; const varName = - PHP.nameDB_.getName(block.getFieldValue('VAR'), NameType.VARIABLE); + phpGenerator.nameDB_.getName( + block.getFieldValue('VAR'), NameType.VARIABLE); return varName + ' += ' + argument0 + ';\n'; }; // Rounding functions have a single operand. -PHP.forBlock['math_round'] = PHP.forBlock['math_single']; +phpGenerator.forBlock['math_round'] = phpGenerator.forBlock['math_single']; // Trigonometry functions have a single operand. -PHP.forBlock['math_trig'] = PHP.forBlock['math_single']; +phpGenerator.forBlock['math_trig'] = phpGenerator.forBlock['math_single']; -PHP.forBlock['math_on_list'] = function(block) { +phpGenerator.forBlock['math_on_list'] = function(block) { // Math functions for lists. const func = block.getFieldValue('OP'); let list; @@ -214,38 +217,41 @@ PHP.forBlock['math_on_list'] = function(block) { switch (func) { case 'SUM': list = - PHP.valueToCode(block, 'LIST', PHP.ORDER_FUNCTION_CALL) || 'array()'; + phpGenerator.valueToCode(block, 'LIST', Order.FUNCTION_CALL) + || 'array()'; code = 'array_sum(' + list + ')'; break; case 'MIN': list = - PHP.valueToCode(block, 'LIST', PHP.ORDER_FUNCTION_CALL) || 'array()'; + phpGenerator.valueToCode(block, 'LIST', Order.FUNCTION_CALL) + || 'array()'; code = 'min(' + list + ')'; break; case 'MAX': list = - PHP.valueToCode(block, 'LIST', PHP.ORDER_FUNCTION_CALL) || 'array()'; + phpGenerator.valueToCode(block, 'LIST', Order.FUNCTION_CALL) + || 'array()'; code = 'max(' + list + ')'; break; case 'AVERAGE': { - const functionName = PHP.provideFunction_('math_mean', ` -function ${PHP.FUNCTION_NAME_PLACEHOLDER_}($myList) { + const functionName = phpGenerator.provideFunction_('math_mean', ` +function ${phpGenerator.FUNCTION_NAME_PLACEHOLDER_}($myList) { return array_sum($myList) / count($myList); } `); - list = PHP.valueToCode(block, 'LIST', PHP.ORDER_NONE) || 'array()'; + list = phpGenerator.valueToCode(block, 'LIST', Order.NONE) || 'array()'; code = functionName + '(' + list + ')'; break; } case 'MEDIAN': { - const functionName = PHP.provideFunction_('math_median', ` -function ${PHP.FUNCTION_NAME_PLACEHOLDER_}($arr) { + const functionName = phpGenerator.provideFunction_('math_median', ` +function ${phpGenerator.FUNCTION_NAME_PLACEHOLDER_}($arr) { sort($arr,SORT_NUMERIC); return (count($arr) % 2) ? $arr[floor(count($arr) / 2)] : ($arr[floor(count($arr) / 2)] + $arr[floor(count($arr) / 2) - 1]) / 2; } `); - list = PHP.valueToCode(block, 'LIST', PHP.ORDER_NONE) || '[]'; + list = phpGenerator.valueToCode(block, 'LIST', Order.NONE) || '[]'; code = functionName + '(' + list + ')'; break; } @@ -253,8 +259,8 @@ function ${PHP.FUNCTION_NAME_PLACEHOLDER_}($arr) { // 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 = PHP.provideFunction_('math_modes', ` -function ${PHP.FUNCTION_NAME_PLACEHOLDER_}($values) { + const functionName = phpGenerator.provideFunction_('math_modes', ` +function ${phpGenerator.FUNCTION_NAME_PLACEHOLDER_}($values) { if (empty($values)) return array(); $counts = array_count_values($values); arsort($counts); // Sort counts in descending order @@ -262,13 +268,14 @@ function ${PHP.FUNCTION_NAME_PLACEHOLDER_}($values) { return $modes; } `); - list = PHP.valueToCode(block, 'LIST', PHP.ORDER_NONE) || '[]'; + list = phpGenerator.valueToCode(block, 'LIST', Order.NONE) || '[]'; code = functionName + '(' + list + ')'; break; } case 'STD_DEV': { - const functionName = PHP.provideFunction_('math_standard_deviation', ` -function ${PHP.FUNCTION_NAME_PLACEHOLDER_}($numbers) { + const functionName = + phpGenerator.provideFunction_('math_standard_deviation', ` +function ${phpGenerator.FUNCTION_NAME_PLACEHOLDER_}($numbers) { $n = count($numbers); if (!$n) return null; $mean = array_sum($numbers) / count($numbers); @@ -276,53 +283,54 @@ function ${PHP.FUNCTION_NAME_PLACEHOLDER_}($numbers) { return sqrt(array_sum($devs) / (count($devs) - 1)); } `); - list = PHP.valueToCode(block, 'LIST', PHP.ORDER_NONE) || '[]'; + list = phpGenerator.valueToCode(block, 'LIST', Order.NONE) || '[]'; code = functionName + '(' + list + ')'; break; } case 'RANDOM': { - const functionName = PHP.provideFunction_('math_random_list', ` -function ${PHP.FUNCTION_NAME_PLACEHOLDER_}($list) { + const functionName = phpGenerator.provideFunction_('math_random_list', ` +function ${phpGenerator.FUNCTION_NAME_PLACEHOLDER_}($list) { $x = rand(0, count($list)-1); return $list[$x]; } `); - list = PHP.valueToCode(block, 'LIST', PHP.ORDER_NONE) || '[]'; + list = phpGenerator.valueToCode(block, 'LIST', Order.NONE) || '[]'; code = functionName + '(' + list + ')'; break; } default: throw Error('Unknown operator: ' + func); } - return [code, PHP.ORDER_FUNCTION_CALL]; + return [code, Order.FUNCTION_CALL]; }; -PHP.forBlock['math_modulo'] = function(block) { +phpGenerator.forBlock['math_modulo'] = function(block) { // Remainder computation. const argument0 = - PHP.valueToCode(block, 'DIVIDEND', PHP.ORDER_MODULUS) || '0'; - const argument1 = PHP.valueToCode(block, 'DIVISOR', PHP.ORDER_MODULUS) || '0'; + phpGenerator.valueToCode(block, 'DIVIDEND', Order.MODULUS) || '0'; + const argument1 = + phpGenerator.valueToCode(block, 'DIVISOR', Order.MODULUS) || '0'; const code = argument0 + ' % ' + argument1; - return [code, PHP.ORDER_MODULUS]; + return [code, Order.MODULUS]; }; -PHP.forBlock['math_constrain'] = function(block) { +phpGenerator.forBlock['math_constrain'] = function(block) { // Constrain a number between two limits. - const argument0 = PHP.valueToCode(block, 'VALUE', PHP.ORDER_NONE) || '0'; - const argument1 = PHP.valueToCode(block, 'LOW', PHP.ORDER_NONE) || '0'; + const argument0 = phpGenerator.valueToCode(block, 'VALUE', Order.NONE) || '0'; + const argument1 = phpGenerator.valueToCode(block, 'LOW', Order.NONE) || '0'; const argument2 = - PHP.valueToCode(block, 'HIGH', PHP.ORDER_NONE) || 'Infinity'; + phpGenerator.valueToCode(block, 'HIGH', Order.NONE) || 'Infinity'; const code = 'min(max(' + argument0 + ', ' + argument1 + '), ' + argument2 + ')'; - return [code, PHP.ORDER_FUNCTION_CALL]; + return [code, Order.FUNCTION_CALL]; }; -PHP.forBlock['math_random_int'] = function(block) { +phpGenerator.forBlock['math_random_int'] = function(block) { // Random integer between [X] and [Y]. - const argument0 = PHP.valueToCode(block, 'FROM', PHP.ORDER_NONE) || '0'; - const argument1 = PHP.valueToCode(block, 'TO', PHP.ORDER_NONE) || '0'; - const functionName = PHP.provideFunction_('math_random_int', ` -function ${PHP.FUNCTION_NAME_PLACEHOLDER_}($a, $b) { + const argument0 = phpGenerator.valueToCode(block, 'FROM', Order.NONE) || '0'; + const argument1 = phpGenerator.valueToCode(block, 'TO', Order.NONE) || '0'; + const functionName = phpGenerator.provideFunction_('math_random_int', ` +function ${phpGenerator.FUNCTION_NAME_PLACEHOLDER_}($a, $b) { if ($a > $b) { return rand($b, $a); } @@ -330,20 +338,20 @@ function ${PHP.FUNCTION_NAME_PLACEHOLDER_}($a, $b) { } `); const code = functionName + '(' + argument0 + ', ' + argument1 + ')'; - return [code, PHP.ORDER_FUNCTION_CALL]; + return [code, Order.FUNCTION_CALL]; }; -PHP.forBlock['math_random_float'] = function(block) { +phpGenerator.forBlock['math_random_float'] = function(block) { // Random fraction between 0 and 1. - return ['(float)rand()/(float)getrandmax()', PHP.ORDER_FUNCTION_CALL]; + return ['(float)rand()/(float)getrandmax()', Order.FUNCTION_CALL]; }; -PHP.forBlock['math_atan2'] = function(block) { +phpGenerator.forBlock['math_atan2'] = function(block) { // Arctangent of point (X, Y) in degrees from -180 to 180. - const argument0 = PHP.valueToCode(block, 'X', PHP.ORDER_NONE) || '0'; - const argument1 = PHP.valueToCode(block, 'Y', PHP.ORDER_NONE) || '0'; + const argument0 = phpGenerator.valueToCode(block, 'X', Order.NONE) || '0'; + const argument1 = phpGenerator.valueToCode(block, 'Y', Order.NONE) || '0'; return [ 'atan2(' + argument1 + ', ' + argument0 + ') / pi() * 180', - PHP.ORDER_DIVISION + Order.DIVISION ]; }; diff --git a/generators/php/procedures.js b/generators/php/procedures.js index 12bdbf3a3..483fd147f 100644 --- a/generators/php/procedures.js +++ b/generators/php/procedures.js @@ -13,10 +13,10 @@ goog.declareModuleId('Blockly.PHP.procedures'); import * as Variables from '../../core/variables.js'; import {NameType} from '../../core/names.js'; -import {phpGenerator as PHP} from '../php.js'; +import {phpGenerator, Order} from '../php.js'; -PHP.forBlock['procedures_defreturn'] = function(block) { +phpGenerator.forBlock['procedures_defreturn'] = function(block) { // Define a procedure with a return value. // First, add a 'global' statement for every variable that is not shadowed by // a local parameter. @@ -26,99 +26,107 @@ PHP.forBlock['procedures_defreturn'] = function(block) { for (let i = 0, variable; variable = usedVariables[i]; i++) { const varName = variable.name; if (block.getVars().indexOf(varName) === -1) { - globals.push(PHP.nameDB_.getName(varName, NameType.VARIABLE)); + globals.push(phpGenerator.nameDB_.getName(varName, NameType.VARIABLE)); } } // Add developer variables. const devVarList = Variables.allDeveloperVariables(workspace); for (let i = 0; i < devVarList.length; i++) { globals.push( - PHP.nameDB_.getName(devVarList[i], NameType.DEVELOPER_VARIABLE)); + phpGenerator.nameDB_.getName( + devVarList[i], NameType.DEVELOPER_VARIABLE)); } const globalStr = - globals.length ? PHP.INDENT + 'global ' + globals.join(', ') + ';\n' : ''; + globals.length ? + phpGenerator.INDENT + 'global ' + globals.join(', ') + ';\n' : ''; const funcName = - PHP.nameDB_.getName(block.getFieldValue('NAME'), NameType.PROCEDURE); + phpGenerator.nameDB_.getName( + block.getFieldValue('NAME'), NameType.PROCEDURE); let xfix1 = ''; - if (PHP.STATEMENT_PREFIX) { - xfix1 += PHP.injectId(PHP.STATEMENT_PREFIX, block); + if (phpGenerator.STATEMENT_PREFIX) { + xfix1 += phpGenerator.injectId(phpGenerator.STATEMENT_PREFIX, block); } - if (PHP.STATEMENT_SUFFIX) { - xfix1 += PHP.injectId(PHP.STATEMENT_SUFFIX, block); + if (phpGenerator.STATEMENT_SUFFIX) { + xfix1 += phpGenerator.injectId(phpGenerator.STATEMENT_SUFFIX, block); } if (xfix1) { - xfix1 = PHP.prefixLines(xfix1, PHP.INDENT); + xfix1 = phpGenerator.prefixLines(xfix1, phpGenerator.INDENT); } let loopTrap = ''; - if (PHP.INFINITE_LOOP_TRAP) { - loopTrap = PHP.prefixLines( - PHP.injectId(PHP.INFINITE_LOOP_TRAP, block), PHP.INDENT); + if (phpGenerator.INFINITE_LOOP_TRAP) { + loopTrap = phpGenerator.prefixLines( + phpGenerator.injectId(phpGenerator.INFINITE_LOOP_TRAP, block), + phpGenerator.INDENT); } - const branch = PHP.statementToCode(block, 'STACK'); - let returnValue = PHP.valueToCode(block, 'RETURN', PHP.ORDER_NONE) || ''; + const branch = phpGenerator.statementToCode(block, 'STACK'); + let returnValue = phpGenerator.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 = PHP.INDENT + 'return ' + returnValue + ';\n'; + returnValue = phpGenerator.INDENT + 'return ' + returnValue + ';\n'; } const args = []; const variables = block.getVars(); for (let i = 0; i < variables.length; i++) { - args[i] = PHP.nameDB_.getName(variables[i], NameType.VARIABLE); + args[i] = phpGenerator.nameDB_.getName(variables[i], NameType.VARIABLE); } let code = 'function ' + funcName + '(' + args.join(', ') + ') {\n' + globalStr + xfix1 + loopTrap + branch + xfix2 + returnValue + '}'; - code = PHP.scrub_(block, code); + code = phpGenerator.scrub_(block, code); // Add % so as not to collide with helper functions in definitions list. - PHP.definitions_['%' + funcName] = code; + phpGenerator.definitions_['%' + funcName] = code; return null; }; // Defining a procedure without a return value uses the same generator as // a procedure with a return value. -PHP.forBlock['procedures_defnoreturn'] = PHP.forBlock['procedures_defreturn']; +phpGenerator.forBlock['procedures_defnoreturn'] = + phpGenerator.forBlock['procedures_defreturn']; -PHP.forBlock['procedures_callreturn'] = function(block) { +phpGenerator.forBlock['procedures_callreturn'] = function(block) { // Call a procedure with a return value. const funcName = - PHP.nameDB_.getName(block.getFieldValue('NAME'), NameType.PROCEDURE); + phpGenerator.nameDB_.getName( + block.getFieldValue('NAME'), NameType.PROCEDURE); const args = []; const variables = block.getVars(); for (let i = 0; i < variables.length; i++) { - args[i] = PHP.valueToCode(block, 'ARG' + i, PHP.ORDER_NONE) || 'null'; + args[i] = phpGenerator.valueToCode(block, 'ARG' + i, Order.NONE) || 'null'; } const code = funcName + '(' + args.join(', ') + ')'; - return [code, PHP.ORDER_FUNCTION_CALL]; + return [code, Order.FUNCTION_CALL]; }; -PHP.forBlock['procedures_callnoreturn'] = function(block) { +phpGenerator.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 = PHP.forBlock['procedures_callreturn'](block); + const tuple = phpGenerator.forBlock['procedures_callreturn'](block); return tuple[0] + ';\n'; }; -PHP.forBlock['procedures_ifreturn'] = function(block) { +phpGenerator.forBlock['procedures_ifreturn'] = function(block) { // Conditionally return value from a procedure. const condition = - PHP.valueToCode(block, 'CONDITION', PHP.ORDER_NONE) || 'false'; + phpGenerator.valueToCode(block, 'CONDITION', Order.NONE) || 'false'; let code = 'if (' + condition + ') {\n'; - if (PHP.STATEMENT_SUFFIX) { + if (phpGenerator.STATEMENT_SUFFIX) { // Inject any statement suffix here since the regular one at the end // will not get executed if the return is triggered. code += - PHP.prefixLines(PHP.injectId(PHP.STATEMENT_SUFFIX, block), PHP.INDENT); + phpGenerator.prefixLines( + phpGenerator.injectId(phpGenerator.STATEMENT_SUFFIX, block), + phpGenerator.INDENT); } if (block.hasReturnValue_) { - const value = PHP.valueToCode(block, 'VALUE', PHP.ORDER_NONE) || 'null'; - code += PHP.INDENT + 'return ' + value + ';\n'; + const value = phpGenerator.valueToCode(block, 'VALUE', Order.NONE) || 'null'; + code += phpGenerator.INDENT + 'return ' + value + ';\n'; } else { - code += PHP.INDENT + 'return;\n'; + code += phpGenerator.INDENT + 'return;\n'; } code += '}\n'; return code; diff --git a/generators/php/text.js b/generators/php/text.js index 83c10a5dd..66e06d869 100644 --- a/generators/php/text.js +++ b/generators/php/text.js @@ -12,151 +12,154 @@ import * as goog from '../../closure/goog/goog.js'; goog.declareModuleId('Blockly.PHP.texts'); import {NameType} from '../../core/names.js'; -import {phpGenerator as PHP} from '../php.js'; +import {phpGenerator, Order} from '../php.js'; -PHP.forBlock['text'] = function(block) { +phpGenerator.forBlock['text'] = function(block) { // Text value. - const code = PHP.quote_(block.getFieldValue('TEXT')); - return [code, PHP.ORDER_ATOMIC]; + const code = phpGenerator.quote_(block.getFieldValue('TEXT')); + return [code, Order.ATOMIC]; }; -PHP.forBlock['text_multiline'] = function(block) { +phpGenerator.forBlock['text_multiline'] = function(block) { // Text value. - const code = PHP.multiline_quote_(block.getFieldValue('TEXT')); + const code = phpGenerator.multiline_quote_(block.getFieldValue('TEXT')); const order = - code.indexOf('.') !== -1 ? PHP.ORDER_STRING_CONCAT : PHP.ORDER_ATOMIC; + code.indexOf('.') !== -1 ? Order.STRING_CONCAT : Order.ATOMIC; return [code, order]; }; -PHP.forBlock['text_join'] = function(block) { +phpGenerator.forBlock['text_join'] = function(block) { // Create a string made up of any number of elements of any type. if (block.itemCount_ === 0) { - return ["''", PHP.ORDER_ATOMIC]; + return ["''", Order.ATOMIC]; } else if (block.itemCount_ === 1) { - const element = PHP.valueToCode(block, 'ADD0', PHP.ORDER_NONE) || "''"; + const element = phpGenerator.valueToCode(block, 'ADD0', Order.NONE) || "''"; const code = element; - return [code, PHP.ORDER_NONE]; + return [code, Order.NONE]; } else if (block.itemCount_ === 2) { const element0 = - PHP.valueToCode(block, 'ADD0', PHP.ORDER_STRING_CONCAT) || "''"; + phpGenerator.valueToCode(block, 'ADD0', Order.STRING_CONCAT) || "''"; const element1 = - PHP.valueToCode(block, 'ADD1', PHP.ORDER_STRING_CONCAT) || "''"; + phpGenerator.valueToCode(block, 'ADD1', Order.STRING_CONCAT) || "''"; const code = element0 + ' . ' + element1; - return [code, PHP.ORDER_STRING_CONCAT]; + return [code, Order.STRING_CONCAT]; } else { const elements = new Array(block.itemCount_); for (let i = 0; i < block.itemCount_; i++) { - elements[i] = PHP.valueToCode(block, 'ADD' + i, PHP.ORDER_NONE) || "''"; + elements[i] = + phpGenerator.valueToCode(block, 'ADD' + i, Order.NONE) || "''"; } const code = 'implode(\'\', array(' + elements.join(',') + '))'; - return [code, PHP.ORDER_FUNCTION_CALL]; + return [code, Order.FUNCTION_CALL]; } }; -PHP.forBlock['text_append'] = function(block) { +phpGenerator.forBlock['text_append'] = function(block) { // Append to a variable in place. const varName = - PHP.nameDB_.getName(block.getFieldValue('VAR'), NameType.VARIABLE); - const value = PHP.valueToCode(block, 'TEXT', PHP.ORDER_ASSIGNMENT) || "''"; + phpGenerator.nameDB_.getName( + block.getFieldValue('VAR'), NameType.VARIABLE); + const value = + phpGenerator.valueToCode(block, 'TEXT', Order.ASSIGNMENT) || "''"; return varName + ' .= ' + value + ';\n'; }; -PHP.forBlock['text_length'] = function(block) { +phpGenerator.forBlock['text_length'] = function(block) { // String or array length. - const functionName = PHP.provideFunction_('length', ` -function ${PHP.FUNCTION_NAME_PLACEHOLDER_}($value) { + const functionName = phpGenerator.provideFunction_('length', ` +function ${phpGenerator.FUNCTION_NAME_PLACEHOLDER_}($value) { if (is_string($value)) { return strlen($value); } return count($value); } `); - const text = PHP.valueToCode(block, 'VALUE', PHP.ORDER_NONE) || "''"; - return [functionName + '(' + text + ')', PHP.ORDER_FUNCTION_CALL]; + const text = phpGenerator.valueToCode(block, 'VALUE', Order.NONE) || "''"; + return [functionName + '(' + text + ')', Order.FUNCTION_CALL]; }; -PHP.forBlock['text_isEmpty'] = function(block) { +phpGenerator.forBlock['text_isEmpty'] = function(block) { // Is the string null or array empty? - const text = PHP.valueToCode(block, 'VALUE', PHP.ORDER_NONE) || "''"; - return ['empty(' + text + ')', PHP.ORDER_FUNCTION_CALL]; + const text = phpGenerator.valueToCode(block, 'VALUE', Order.NONE) || "''"; + return ['empty(' + text + ')', Order.FUNCTION_CALL]; }; -PHP.forBlock['text_indexOf'] = function(block) { +phpGenerator.forBlock['text_indexOf'] = function(block) { // Search the text for a substring. const operator = block.getFieldValue('END') === 'FIRST' ? 'strpos' : 'strrpos'; - const substring = PHP.valueToCode(block, 'FIND', PHP.ORDER_NONE) || "''"; - const text = PHP.valueToCode(block, 'VALUE', PHP.ORDER_NONE) || "''"; + const substring = phpGenerator.valueToCode(block, 'FIND', Order.NONE) || "''"; + const text = phpGenerator.valueToCode(block, 'VALUE', Order.NONE) || "''"; let errorIndex = ' -1'; let indexAdjustment = ''; if (block.workspace.options.oneBasedIndex) { errorIndex = ' 0'; indexAdjustment = ' + 1'; } - const functionName = PHP.provideFunction_( + const functionName = phpGenerator.provideFunction_( block.getFieldValue('END') === 'FIRST' ? 'text_indexOf' : 'text_lastIndexOf', ` -function ${PHP.FUNCTION_NAME_PLACEHOLDER_}($text, $search) { +function ${phpGenerator.FUNCTION_NAME_PLACEHOLDER_}($text, $search) { $pos = ${operator}($text, $search); return $pos === false ? ${errorIndex} : $pos${indexAdjustment}; } `); const code = functionName + '(' + text + ', ' + substring + ')'; - return [code, PHP.ORDER_FUNCTION_CALL]; + return [code, Order.FUNCTION_CALL]; }; -PHP.forBlock['text_charAt'] = function(block) { +phpGenerator.forBlock['text_charAt'] = function(block) { // Get letter at index. const where = block.getFieldValue('WHERE') || 'FROM_START'; - const textOrder = (where === 'RANDOM') ? PHP.ORDER_NONE : PHP.ORDER_NONE; - const text = PHP.valueToCode(block, 'VALUE', textOrder) || "''"; + const textOrder = (where === 'RANDOM') ? Order.NONE : Order.NONE; + const text = phpGenerator.valueToCode(block, 'VALUE', textOrder) || "''"; switch (where) { case 'FIRST': { const code = 'substr(' + text + ', 0, 1)'; - return [code, PHP.ORDER_FUNCTION_CALL]; + return [code, Order.FUNCTION_CALL]; } case 'LAST': { const code = 'substr(' + text + ', -1)'; - return [code, PHP.ORDER_FUNCTION_CALL]; + return [code, Order.FUNCTION_CALL]; } case 'FROM_START': { - const at = PHP.getAdjusted(block, 'AT'); + const at = phpGenerator.getAdjusted(block, 'AT'); const code = 'substr(' + text + ', ' + at + ', 1)'; - return [code, PHP.ORDER_FUNCTION_CALL]; + return [code, Order.FUNCTION_CALL]; } case 'FROM_END': { - const at = PHP.getAdjusted(block, 'AT', 1, true); + const at = phpGenerator.getAdjusted(block, 'AT', 1, true); const code = 'substr(' + text + ', ' + at + ', 1)'; - return [code, PHP.ORDER_FUNCTION_CALL]; + return [code, Order.FUNCTION_CALL]; } case 'RANDOM': { - const functionName = PHP.provideFunction_('text_random_letter', ` -function ${PHP.FUNCTION_NAME_PLACEHOLDER_}($text) { + const functionName = phpGenerator.provideFunction_('text_random_letter', ` +function ${phpGenerator.FUNCTION_NAME_PLACEHOLDER_}($text) { return $text[rand(0, strlen($text) - 1)]; } `); const code = functionName + '(' + text + ')'; - return [code, PHP.ORDER_FUNCTION_CALL]; + return [code, Order.FUNCTION_CALL]; } } throw Error('Unhandled option (text_charAt).'); }; -PHP.forBlock['text_getSubstring'] = function(block) { +phpGenerator.forBlock['text_getSubstring'] = function(block) { // Get substring. const where1 = block.getFieldValue('WHERE1'); const where2 = block.getFieldValue('WHERE2'); - const text = PHP.valueToCode(block, 'STRING', PHP.ORDER_NONE) || "''"; + const text = phpGenerator.valueToCode(block, 'STRING', Order.NONE) || "''"; if (where1 === 'FIRST' && where2 === 'LAST') { const code = text; - return [code, PHP.ORDER_NONE]; + return [code, Order.NONE]; } else { - const at1 = PHP.getAdjusted(block, 'AT1'); - const at2 = PHP.getAdjusted(block, 'AT2'); - const functionName = PHP.provideFunction_('text_get_substring', ` -function ${PHP.FUNCTION_NAME_PLACEHOLDER_}($text, $where1, $at1, $where2, $at2) { + const at1 = phpGenerator.getAdjusted(block, 'AT1'); + const at2 = phpGenerator.getAdjusted(block, 'AT2'); + const functionName = phpGenerator.provideFunction_('text_get_substring', ` +function ${phpGenerator.FUNCTION_NAME_PLACEHOLDER_}($text, $where1, $at1, $where2, $at2) { if ($where1 == 'FROM_END') { $at1 = strlen($text) - 1 - $at1; } else if ($where1 == 'FIRST') { @@ -179,13 +182,13 @@ function ${PHP.FUNCTION_NAME_PLACEHOLDER_}($text, $where1, $at1, $where2, $at2) `); const code = functionName + '(' + text + ', \'' + where1 + '\', ' + at1 + ', \'' + where2 + '\', ' + at2 + ')'; - return [code, PHP.ORDER_FUNCTION_CALL]; + return [code, Order.FUNCTION_CALL]; } }; -PHP.forBlock['text_changeCase'] = function(block) { +phpGenerator.forBlock['text_changeCase'] = function(block) { // Change capitalization. - const text = PHP.valueToCode(block, 'TEXT', PHP.ORDER_NONE) || "''"; + const text = phpGenerator.valueToCode(block, 'TEXT', Order.NONE) || "''"; let code; if (block.getFieldValue('CASE') === 'UPPERCASE') { code = 'strtoupper(' + text + ')'; @@ -194,62 +197,62 @@ PHP.forBlock['text_changeCase'] = function(block) { } else if (block.getFieldValue('CASE') === 'TITLECASE') { code = 'ucwords(strtolower(' + text + '))'; } - return [code, PHP.ORDER_FUNCTION_CALL]; + return [code, Order.FUNCTION_CALL]; }; -PHP.forBlock['text_trim'] = function(block) { +phpGenerator.forBlock['text_trim'] = function(block) { // Trim spaces. const OPERATORS = {'LEFT': 'ltrim', 'RIGHT': 'rtrim', 'BOTH': 'trim'}; const operator = OPERATORS[block.getFieldValue('MODE')]; - const text = PHP.valueToCode(block, 'TEXT', PHP.ORDER_NONE) || "''"; - return [operator + '(' + text + ')', PHP.ORDER_FUNCTION_CALL]; + const text = phpGenerator.valueToCode(block, 'TEXT', Order.NONE) || "''"; + return [operator + '(' + text + ')', Order.FUNCTION_CALL]; }; -PHP.forBlock['text_print'] = function(block) { +phpGenerator.forBlock['text_print'] = function(block) { // Print statement. - const msg = PHP.valueToCode(block, 'TEXT', PHP.ORDER_NONE) || "''"; + const msg = phpGenerator.valueToCode(block, 'TEXT', Order.NONE) || "''"; return 'print(' + msg + ');\n'; }; -PHP.forBlock['text_prompt_ext'] = function(block) { +phpGenerator.forBlock['text_prompt_ext'] = function(block) { // Prompt function. let msg; if (block.getField('TEXT')) { // Internal message. - msg = PHP.quote_(block.getFieldValue('TEXT')); + msg = phpGenerator.quote_(block.getFieldValue('TEXT')); } else { // External message. - msg = PHP.valueToCode(block, 'TEXT', PHP.ORDER_NONE) || "''"; + msg = phpGenerator.valueToCode(block, 'TEXT', Order.NONE) || "''"; } let code = 'readline(' + msg + ')'; const toNumber = block.getFieldValue('TYPE') === 'NUMBER'; if (toNumber) { code = 'floatval(' + code + ')'; } - return [code, PHP.ORDER_FUNCTION_CALL]; + return [code, Order.FUNCTION_CALL]; }; -PHP.forBlock['text_prompt'] = PHP.forBlock['text_prompt_ext']; +phpGenerator.forBlock['text_prompt'] = phpGenerator.forBlock['text_prompt_ext']; -PHP.forBlock['text_count'] = function(block) { - const text = PHP.valueToCode(block, 'TEXT', PHP.ORDER_NONE) || "''"; - const sub = PHP.valueToCode(block, 'SUB', PHP.ORDER_NONE) || "''"; +phpGenerator.forBlock['text_count'] = function(block) { + const text = phpGenerator.valueToCode(block, 'TEXT', Order.NONE) || "''"; + const sub = phpGenerator.valueToCode(block, 'SUB', Order.NONE) || "''"; const code = 'strlen(' + sub + ') === 0' + ' ? strlen(' + text + ') + 1' + ' : substr_count(' + text + ', ' + sub + ')'; - return [code, PHP.ORDER_CONDITIONAL]; + return [code, Order.CONDITIONAL]; }; -PHP.forBlock['text_replace'] = function(block) { - const text = PHP.valueToCode(block, 'TEXT', PHP.ORDER_NONE) || "''"; - const from = PHP.valueToCode(block, 'FROM', PHP.ORDER_NONE) || "''"; - const to = PHP.valueToCode(block, 'TO', PHP.ORDER_NONE) || "''"; +phpGenerator.forBlock['text_replace'] = function(block) { + const text = phpGenerator.valueToCode(block, 'TEXT', Order.NONE) || "''"; + const from = phpGenerator.valueToCode(block, 'FROM', Order.NONE) || "''"; + const to = phpGenerator.valueToCode(block, 'TO', Order.NONE) || "''"; const code = 'str_replace(' + from + ', ' + to + ', ' + text + ')'; - return [code, PHP.ORDER_FUNCTION_CALL]; + return [code, Order.FUNCTION_CALL]; }; -PHP.forBlock['text_reverse'] = function(block) { - const text = PHP.valueToCode(block, 'TEXT', PHP.ORDER_NONE) || "''"; +phpGenerator.forBlock['text_reverse'] = function(block) { + const text = phpGenerator.valueToCode(block, 'TEXT', Order.NONE) || "''"; const code = 'strrev(' + text + ')'; - return [code, PHP.ORDER_FUNCTION_CALL]; + return [code, Order.FUNCTION_CALL]; }; diff --git a/generators/php/variables.js b/generators/php/variables.js index 50f4a9e9b..812c3770d 100644 --- a/generators/php/variables.js +++ b/generators/php/variables.js @@ -12,21 +12,23 @@ import * as goog from '../../closure/goog/goog.js'; goog.declareModuleId('Blockly.PHP.variables'); import {NameType} from '../../core/names.js'; -import {phpGenerator as PHP} from '../php.js'; +import {phpGenerator, Order} from '../php.js'; -PHP.forBlock['variables_get'] = function(block) { +phpGenerator.forBlock['variables_get'] = function(block) { // Variable getter. const code = - PHP.nameDB_.getName(block.getFieldValue('VAR'), NameType.VARIABLE); - return [code, PHP.ORDER_ATOMIC]; + phpGenerator.nameDB_.getName( + block.getFieldValue('VAR'), NameType.VARIABLE); + return [code, Order.ATOMIC]; }; -PHP.forBlock['variables_set'] = function(block) { +phpGenerator.forBlock['variables_set'] = function(block) { // Variable setter. const argument0 = - PHP.valueToCode(block, 'VALUE', PHP.ORDER_ASSIGNMENT) || '0'; + phpGenerator.valueToCode(block, 'VALUE', Order.ASSIGNMENT) || '0'; const varName = - PHP.nameDB_.getName(block.getFieldValue('VAR'), NameType.VARIABLE); + phpGenerator.nameDB_.getName( + block.getFieldValue('VAR'), NameType.VARIABLE); return varName + ' = ' + argument0 + ';\n'; }; diff --git a/generators/php/variables_dynamic.js b/generators/php/variables_dynamic.js index 88732aebc..01eaf3661 100644 --- a/generators/php/variables_dynamic.js +++ b/generators/php/variables_dynamic.js @@ -11,10 +11,12 @@ import * as goog from '../../closure/goog/goog.js'; goog.declareModuleId('Blockly.PHP.variablesDynamic'); -import {phpGenerator as PHP} from '../php.js'; +import {phpGenerator} from '../php.js'; import './variables.js'; -// PHP is dynamically typed. -PHP.forBlock['variables_get_dynamic'] = PHP.forBlock['variables_get']; -PHP.forBlock['variables_set_dynamic'] = PHP.forBlock['variables_set']; +// phpGenerator is dynamically typed. +phpGenerator.forBlock['variables_get_dynamic'] = + phpGenerator.forBlock['variables_get']; +phpGenerator.forBlock['variables_set_dynamic'] = + phpGenerator.forBlock['variables_set'];