diff options
Diffstat (limited to 'blockly/generators/javascript/loops.js')
-rw-r--r-- | blockly/generators/javascript/loops.js | 175 |
1 files changed, 175 insertions, 0 deletions
diff --git a/blockly/generators/javascript/loops.js b/blockly/generators/javascript/loops.js new file mode 100644 index 0000000..1a2ade5 --- /dev/null +++ b/blockly/generators/javascript/loops.js @@ -0,0 +1,175 @@ +/** + * @license + * Visual Blocks Language + * + * Copyright 2012 Google Inc. + * https://developers.google.com/blockly/ + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @fileoverview Generating JavaScript for loop blocks. + * @author fraser@google.com (Neil Fraser) + */ +'use strict'; + +goog.provide('Blockly.JavaScript.loops'); + +goog.require('Blockly.JavaScript'); + + +Blockly.JavaScript['controls_repeat_ext'] = function(block) { + // Repeat n times. + if (block.getField('TIMES')) { + // Internal number. + var repeats = String(Number(block.getFieldValue('TIMES'))); + } else { + // External number. + var repeats = Blockly.JavaScript.valueToCode(block, 'TIMES', + Blockly.JavaScript.ORDER_ASSIGNMENT) || '0'; + } + var branch = Blockly.JavaScript.statementToCode(block, 'DO'); + branch = Blockly.JavaScript.addLoopTrap(branch, block.id); + var code = ''; + var loopVar = Blockly.JavaScript.variableDB_.getDistinctName( + 'count', Blockly.Variables.NAME_TYPE); + var endVar = repeats; + if (!repeats.match(/^\w+$/) && !Blockly.isNumber(repeats)) { + var endVar = Blockly.JavaScript.variableDB_.getDistinctName( + 'repeat_end', Blockly.Variables.NAME_TYPE); + code += 'var ' + endVar + ' = ' + repeats + ';\n'; + } + code += 'for (var ' + loopVar + ' = 0; ' + + loopVar + ' < ' + endVar + '; ' + + loopVar + '++) {\n' + + branch + '}\n'; + return code; +}; + +Blockly.JavaScript['controls_repeat'] = + Blockly.JavaScript['controls_repeat_ext']; + +Blockly.JavaScript['controls_whileUntil'] = function(block) { + // Do while/until loop. + var until = block.getFieldValue('MODE') == 'UNTIL'; + var argument0 = Blockly.JavaScript.valueToCode(block, 'BOOL', + until ? Blockly.JavaScript.ORDER_LOGICAL_NOT : + Blockly.JavaScript.ORDER_NONE) || 'false'; + var branch = Blockly.JavaScript.statementToCode(block, 'DO'); + branch = Blockly.JavaScript.addLoopTrap(branch, block.id); + if (until) { + argument0 = '!' + argument0; + } + return 'while (' + argument0 + ') {\n' + branch + '}\n'; +}; + +Blockly.JavaScript['controls_for'] = function(block) { + // For loop. + var variable0 = Blockly.JavaScript.variableDB_.getName( + block.getFieldValue('VAR'), Blockly.Variables.NAME_TYPE); + var argument0 = Blockly.JavaScript.valueToCode(block, 'FROM', + Blockly.JavaScript.ORDER_ASSIGNMENT) || '0'; + var argument1 = Blockly.JavaScript.valueToCode(block, 'TO', + Blockly.JavaScript.ORDER_ASSIGNMENT) || '0'; + var increment = Blockly.JavaScript.valueToCode(block, 'BY', + Blockly.JavaScript.ORDER_ASSIGNMENT) || '1'; + var branch = Blockly.JavaScript.statementToCode(block, 'DO'); + branch = Blockly.JavaScript.addLoopTrap(branch, block.id); + var code; + if (Blockly.isNumber(argument0) && Blockly.isNumber(argument1) && + Blockly.isNumber(increment)) { + // All arguments are simple numbers. + var up = parseFloat(argument0) <= parseFloat(argument1); + code = 'for (' + variable0 + ' = ' + argument0 + '; ' + + variable0 + (up ? ' <= ' : ' >= ') + argument1 + '; ' + + variable0; + var step = Math.abs(parseFloat(increment)); + if (step == 1) { + code += up ? '++' : '--'; + } else { + code += (up ? ' += ' : ' -= ') + step; + } + code += ') {\n' + branch + '}\n'; + } else { + code = ''; + // Cache non-trivial values to variables to prevent repeated look-ups. + var startVar = argument0; + if (!argument0.match(/^\w+$/) && !Blockly.isNumber(argument0)) { + startVar = Blockly.JavaScript.variableDB_.getDistinctName( + variable0 + '_start', Blockly.Variables.NAME_TYPE); + code += 'var ' + startVar + ' = ' + argument0 + ';\n'; + } + var endVar = argument1; + if (!argument1.match(/^\w+$/) && !Blockly.isNumber(argument1)) { + var endVar = Blockly.JavaScript.variableDB_.getDistinctName( + variable0 + '_end', Blockly.Variables.NAME_TYPE); + code += 'var ' + endVar + ' = ' + argument1 + ';\n'; + } + // Determine loop direction at start, in case one of the bounds + // changes during loop execution. + var incVar = Blockly.JavaScript.variableDB_.getDistinctName( + variable0 + '_inc', Blockly.Variables.NAME_TYPE); + code += 'var ' + incVar + ' = '; + if (Blockly.isNumber(increment)) { + code += Math.abs(increment) + ';\n'; + } else { + code += 'Math.abs(' + increment + ');\n'; + } + code += 'if (' + startVar + ' > ' + endVar + ') {\n'; + code += Blockly.JavaScript.INDENT + incVar + ' = -' + incVar + ';\n'; + code += '}\n'; + code += 'for (' + variable0 + ' = ' + startVar + '; ' + + incVar + ' >= 0 ? ' + + variable0 + ' <= ' + endVar + ' : ' + + variable0 + ' >= ' + endVar + '; ' + + variable0 + ' += ' + incVar + ') {\n' + + branch + '}\n'; + } + return code; +}; + +Blockly.JavaScript['controls_forEach'] = function(block) { + // For each loop. + var variable0 = Blockly.JavaScript.variableDB_.getName( + block.getFieldValue('VAR'), Blockly.Variables.NAME_TYPE); + var argument0 = Blockly.JavaScript.valueToCode(block, 'LIST', + Blockly.JavaScript.ORDER_ASSIGNMENT) || '[]'; + var branch = Blockly.JavaScript.statementToCode(block, 'DO'); + branch = Blockly.JavaScript.addLoopTrap(branch, block.id); + var code = ''; + // Cache non-trivial values to variables to prevent repeated look-ups. + var listVar = argument0; + if (!argument0.match(/^\w+$/)) { + listVar = Blockly.JavaScript.variableDB_.getDistinctName( + variable0 + '_list', Blockly.Variables.NAME_TYPE); + code += 'var ' + listVar + ' = ' + argument0 + ';\n'; + } + var indexVar = Blockly.JavaScript.variableDB_.getDistinctName( + variable0 + '_index', Blockly.Variables.NAME_TYPE); + branch = Blockly.JavaScript.INDENT + variable0 + ' = ' + + listVar + '[' + indexVar + '];\n' + branch; + code += 'for (var ' + indexVar + ' in ' + listVar + ') {\n' + branch + '}\n'; + return code; +}; + +Blockly.JavaScript['controls_flow_statements'] = function(block) { + // Flow statements: continue, break. + switch (block.getFieldValue('FLOW')) { + case 'BREAK': + return 'break;\n'; + case 'CONTINUE': + return 'continue;\n'; + } + throw 'Unknown flow statement.'; +}; |