diff --git a/core/field_angle.js b/core/field_angle.js
index 00b0c16a4..9cb5675f4 100644
--- a/core/field_angle.js
+++ b/core/field_angle.js
@@ -154,15 +154,15 @@ Blockly.FieldAngle.prototype.showEditor_ = function() {
'y1': Blockly.FieldAngle.HALF,
'class': 'blocklyAngleLine'}, svg);
// Draw markers around the edge.
- for (var a = 0; a < 360; a += 15) {
+ for (var angle = 0; angle < 360; angle += 15) {
Blockly.createSvgElement('line', {
'x1': Blockly.FieldAngle.HALF + Blockly.FieldAngle.RADIUS,
'y1': Blockly.FieldAngle.HALF,
'x2': Blockly.FieldAngle.HALF + Blockly.FieldAngle.RADIUS -
- (a % 45 == 0 ? 10 : 5),
+ (angle % 45 == 0 ? 10 : 5),
'y2': Blockly.FieldAngle.HALF,
'class': 'blocklyAngleMarks',
- 'transform': 'rotate(' + a + ',' +
+ 'transform': 'rotate(' + angle + ',' +
Blockly.FieldAngle.HALF + ',' + Blockly.FieldAngle.HALF + ')'
}, svg);
}
diff --git a/core/field_dropdown.js b/core/field_dropdown.js
index 1e62cf50c..ec3dd4f5a 100644
--- a/core/field_dropdown.js
+++ b/core/field_dropdown.js
@@ -122,9 +122,9 @@ Blockly.FieldDropdown.prototype.showEditor_ = function() {
var menu = new goog.ui.Menu();
menu.setRightToLeft(this.sourceBlock_.RTL);
var options = this.getOptions_();
- for (var x = 0; x < options.length; x++) {
- var text = options[x][0]; // Human-readable text.
- var value = options[x][1]; // Language-neutral value.
+ for (var i = 0; i < options.length; i++) {
+ var text = options[i][0]; // Human-readable text.
+ var value = options[i][1]; // Language-neutral value.
var menuItem = new goog.ui.MenuItem(text);
menuItem.setRightToLeft(this.sourceBlock_.RTL);
menuItem.setValue(value);
@@ -223,11 +223,11 @@ Blockly.FieldDropdown.prototype.trimOptions_ = function() {
}
// Remove the prefix and suffix from the options.
var newOptions = [];
- for (var x = 0; x < options.length; x++) {
- var text = options[x][0];
- var value = options[x][1];
+ for (var i = 0; i < options.length; i++) {
+ var text = options[i][0];
+ var value = options[i][1];
text = text.substring(prefixLength, text.length - suffixLength);
- newOptions[x] = [text, value];
+ newOptions[i] = [text, value];
}
this.menuGenerator_ = newOptions;
};
@@ -268,10 +268,10 @@ Blockly.FieldDropdown.prototype.setValue = function(newValue) {
this.value_ = newValue;
// Look up and display the human-readable text.
var options = this.getOptions_();
- for (var x = 0; x < options.length; x++) {
+ for (var i = 0; i < options.length; i++) {
// Options are tuples of human-readable text and language-neutral values.
- if (options[x][1] == newValue) {
- this.setText(options[x][0]);
+ if (options[i][1] == newValue) {
+ this.setText(options[i][0]);
return;
}
}
diff --git a/core/field_variable.js b/core/field_variable.js
index cf903c04c..3c6491794 100644
--- a/core/field_variable.js
+++ b/core/field_variable.js
@@ -113,8 +113,8 @@ Blockly.FieldVariable.dropdownCreate = function() {
// Variables are not language-specific, use the name as both the user-facing
// text and the internal representation.
var options = [];
- for (var x = 0; x < variableList.length; x++) {
- options[x] = [variableList[x], variableList[x]];
+ for (var i = 0; i < variableList.length; i++) {
+ options[i] = [variableList[i], variableList[i]];
}
return options;
};
diff --git a/core/generator.js b/core/generator.js
index 8ee110f86..fecc35531 100644
--- a/core/generator.js
+++ b/core/generator.js
@@ -132,7 +132,7 @@ Blockly.Generator.prototype.workspaceToCode = function(workspace) {
* @return {string} The prefixed lines of code.
*/
Blockly.Generator.prototype.prefixLines = function(text, prefix) {
- return prefix + text.replace(/\n(.)/g, '\n' + prefix + '$1');
+ return prefix + text.replace(/(?!\n$)\n/g, '\n' + prefix);
};
/**
@@ -143,8 +143,8 @@ Blockly.Generator.prototype.prefixLines = function(text, prefix) {
Blockly.Generator.prototype.allNestedComments = function(block) {
var comments = [];
var blocks = block.getDescendants();
- for (var x = 0; x < blocks.length; x++) {
- var comment = blocks[x].getCommentText();
+ for (var i = 0; i < blocks.length; i++) {
+ var comment = blocks[i].getCommentText();
if (comment) {
comments.push(comment);
}
diff --git a/core/input.js b/core/input.js
index 346b053cb..4b4eb1df9 100644
--- a/core/input.js
+++ b/core/input.js
@@ -222,8 +222,8 @@ Blockly.Input.prototype.init = function() {
if (!this.sourceBlock_.workspace.rendered) {
return; // Headless blocks don't need fields initialized.
}
- for (var x = 0; x < this.fieldRow.length; x++) {
- this.fieldRow[x].init();
+ for (var i = 0; i < this.fieldRow.length; i++) {
+ this.fieldRow[i].init();
}
};
diff --git a/core/procedures.js b/core/procedures.js
index f98fbd92a..34419fb54 100644
--- a/core/procedures.js
+++ b/core/procedures.js
@@ -197,9 +197,9 @@ Blockly.Procedures.flyoutCategory = function(workspace) {
var mutation = goog.dom.createDom('mutation');
mutation.setAttribute('name', name);
block.appendChild(mutation);
- for (var t = 0; t < args.length; t++) {
+ for (var j = 0; j < args.length; j++) {
var arg = goog.dom.createDom('arg');
- arg.setAttribute('name', args[t]);
+ arg.setAttribute('name', args[j]);
mutation.appendChild(arg);
}
xmlList.push(block);
diff --git a/core/rendered_connection.js b/core/rendered_connection.js
index ef7130dc6..552248526 100644
--- a/core/rendered_connection.js
+++ b/core/rendered_connection.js
@@ -234,8 +234,8 @@ Blockly.RenderedConnection.prototype.unhideAll = function() {
// Show all connections of this block.
connections = block.getConnections_(true);
}
- for (var c = 0; c < connections.length; c++) {
- renderList.push.apply(renderList, connections[c].unhideAll());
+ for (var i = 0; i < connections.length; i++) {
+ renderList.push.apply(renderList, connections[i].unhideAll());
}
if (!renderList.length) {
// Leaf block.
@@ -275,17 +275,17 @@ Blockly.RenderedConnection.prototype.hideAll = function() {
this.setHidden(true);
if (this.targetConnection) {
var blocks = this.targetBlock().getDescendants();
- for (var b = 0; b < blocks.length; b++) {
- var block = blocks[b];
+ for (var i = 0; i < blocks.length; i++) {
+ var block = blocks[i];
// Hide all connections of all children.
var connections = block.getConnections_(true);
- for (var c = 0; c < connections.length; c++) {
- connections[c].setHidden(true);
+ for (var j = 0; j < connections.length; j++) {
+ connections[j].setHidden(true);
}
// Close all bubbles of all children.
var icons = block.getIcons();
- for (var i = 0; i < icons.length; i++) {
- icons[i].setVisible(false);
+ for (var j = 0; j < icons.length; j++) {
+ icons[j].setVisible(false);
}
}
}
diff --git a/core/variables.js b/core/variables.js
index 9399177fe..450d33fcf 100644
--- a/core/variables.js
+++ b/core/variables.js
@@ -54,10 +54,10 @@ Blockly.Variables.allVariables = function(root) {
}
var variableHash = Object.create(null);
// Iterate through every block and add each variable to the hash.
- for (var x = 0; x < blocks.length; x++) {
- var blockVariables = blocks[x].getVars();
- for (var y = 0; y < blockVariables.length; y++) {
- var varName = blockVariables[y];
+ for (var i = 0; i < blocks.length; i++) {
+ var blockVariables = blocks[i].getVars();
+ for (var j = 0; j < blockVariables.length; j++) {
+ var varName = blockVariables[j];
// Variable name may be null if the block is only half-built.
if (varName) {
variableHash[varName.toLowerCase()] = varName;
diff --git a/demos/blockfactory/blocks.js b/demos/blockfactory/blocks.js
index 5008e6a20..012c76fe0 100644
--- a/demos/blockfactory/blocks.js
+++ b/demos/blockfactory/blocks.js
@@ -505,13 +505,13 @@ Blockly.Blocks['type_group'] = {
// Parse XML to restore the group of types.
this.typeCount_ = parseInt(container.getAttribute('types'), 10);
this.updateShape_();
- for (var x = 0; x < this.typeCount_; x++) {
- this.removeInput('TYPE' + x);
+ for (var i = 0; i < this.typeCount_; i++) {
+ this.removeInput('TYPE' + i);
}
- for (var x = 0; x < this.typeCount_; x++) {
- var input = this.appendValueInput('TYPE' + x)
+ for (var i = 0; i < this.typeCount_; i++) {
+ var input = this.appendValueInput('TYPE' + i)
.setCheck('Type');
- if (x == 0) {
+ if (i == 0) {
input.appendField('any of');
}
}
diff --git a/demos/blockfactory/factory.js b/demos/blockfactory/factory.js
index 3e1cf16a0..1bfdf6ce9 100644
--- a/demos/blockfactory/factory.js
+++ b/demos/blockfactory/factory.js
@@ -501,8 +501,8 @@ function getTypesFrom_(block, name) {
types = [escapeString(typeBlock.getFieldValue('TYPE'))];
} else if (typeBlock.type == 'type_group') {
types = [];
- for (var n = 0; n < typeBlock.typeCount_; n++) {
- types = types.concat(getTypesFrom_(typeBlock, 'TYPE' + n));
+ for (var i = 0; i < typeBlock.typeCount_; i++) {
+ types = types.concat(getTypesFrom_(typeBlock, 'TYPE' + i));
}
// Remove duplicates.
var hash = Object.create(null);
diff --git a/generators/dart.js b/generators/dart.js
index f0d7715ea..6fb1236d4 100644
--- a/generators/dart.js
+++ b/generators/dart.js
@@ -45,16 +45,28 @@ Blockly.Dart = new Blockly.Generator('Dart');
Blockly.Dart.addReservedWords(
// https://www.dartlang.org/docs/spec/latest/dart-language-specification.pdf
// Section 16.1.1
- 'assert,break,case,catch,class,const,continue,default,do,else,enum,extends,false,final,finally,for,if,in,is,new,null,rethrow,return,super,switch,this,throw,true,try,var,void,while,with,' +
+ 'assert,break,case,catch,class,const,continue,default,do,else,enum,' +
+ 'extends,false,final,finally,for,if,in,is,new,null,rethrow,return,super,' +
+ 'switch,this,throw,true,try,var,void,while,with,' +
// https://api.dartlang.org/dart_core.html
- 'print,identityHashCode,identical,BidirectionalIterator,Comparable,double,Function,int,Invocation,Iterable,Iterator,List,Map,Match,num,Pattern,RegExp,Set,StackTrace,String,StringSink,Type,bool,DateTime,Deprecated,Duration,Expando,Null,Object,RuneIterator,Runes,Stopwatch,StringBuffer,Symbol,Uri,Comparator,AbstractClassInstantiationError,ArgumentError,AssertionError,CastError,ConcurrentModificationError,CyclicInitializationError,Error,Exception,FallThroughError,FormatException,IntegerDivisionByZeroException,NoSuchMethodError,NullThrownError,OutOfMemoryError,RangeError,StackOverflowError,StateError,TypeError,UnimplementedError,UnsupportedError');
+ 'print,identityHashCode,identical,BidirectionalIterator,Comparable,' +
+ 'double,Function,int,Invocation,Iterable,Iterator,List,Map,Match,num,' +
+ 'Pattern,RegExp,Set,StackTrace,String,StringSink,Type,bool,DateTime,' +
+ 'Deprecated,Duration,Expando,Null,Object,RuneIterator,Runes,Stopwatch,' +
+ 'StringBuffer,Symbol,Uri,Comparator,AbstractClassInstantiationError,' +
+ 'ArgumentError,AssertionError,CastError,ConcurrentModificationError,' +
+ 'CyclicInitializationError,Error,Exception,FallThroughError,' +
+ 'FormatException,IntegerDivisionByZeroException,NoSuchMethodError,' +
+ 'NullThrownError,OutOfMemoryError,RangeError,StackOverflowError,' +
+ 'StateError,TypeError,UnimplementedError,UnsupportedError'
+);
/**
* Order of operation ENUMs.
* https://www.dartlang.org/docs/dart-up-and-running/ch02.html#operator_table
*/
Blockly.Dart.ORDER_ATOMIC = 0; // 0 "" ...
-Blockly.Dart.ORDER_UNARY_POSTFIX = 1; // expr++ expr-- () [] .
+Blockly.Dart.ORDER_UNARY_POSTFIX = 1; // expr++ expr-- () [] . ?.
Blockly.Dart.ORDER_UNARY_PREFIX = 2; // -expr !expr ~expr ++expr --expr
Blockly.Dart.ORDER_MULTIPLICATIVE = 3; // * / % ~/
Blockly.Dart.ORDER_ADDITIVE = 4; // + -
@@ -66,11 +78,18 @@ Blockly.Dart.ORDER_RELATIONAL = 9; // >= > <= < as is is!
Blockly.Dart.ORDER_EQUALITY = 10; // == !=
Blockly.Dart.ORDER_LOGICAL_AND = 11; // &&
Blockly.Dart.ORDER_LOGICAL_OR = 12; // ||
-Blockly.Dart.ORDER_CONDITIONAL = 13; // expr ? expr : expr
-Blockly.Dart.ORDER_CASCADE = 14; // ..
-Blockly.Dart.ORDER_ASSIGNMENT = 15; // = *= /= ~/= %= += -= <<= >>= &= ^= |=
+Blockly.Dart.ORDER_IF_NULL = 13; // ??
+Blockly.Dart.ORDER_CONDITIONAL = 14; // expr ? expr : expr
+Blockly.Dart.ORDER_CASCADE = 15; // ..
+Blockly.Dart.ORDER_ASSIGNMENT = 16; // = *= /= ~/= %= += -= <<= >>= &= ^= |=
Blockly.Dart.ORDER_NONE = 99; // (...)
+/**
+ * Allow for switching between one and zero based indexing for lists and text,
+ * one based by default.
+ */
+Blockly.Dart.ONE_BASED_INDEXING = true;
+
/**
* Initialise the database of variable names.
* @param {!Blockly.Workspace} workspace Workspace to generate code from.
@@ -182,9 +201,9 @@ Blockly.Dart.scrub_ = function(block, code) {
}
// Collect comments for all value arguments.
// Don't collect comments for nested statements.
- for (var x = 0; x < block.inputList.length; x++) {
- if (block.inputList[x].type == Blockly.INPUT_VALUE) {
- var childBlock = block.inputList[x].connection.targetBlock();
+ for (var i = 0; i < block.inputList.length; i++) {
+ if (block.inputList[i].type == Blockly.INPUT_VALUE) {
+ var childBlock = block.inputList[i].connection.targetBlock();
if (childBlock) {
var comment = Blockly.Dart.allNestedComments(childBlock);
if (comment) {
@@ -198,3 +217,63 @@ Blockly.Dart.scrub_ = function(block, code) {
var nextCode = Blockly.Dart.blockToCode(nextBlock);
return commentCode + code + nextCode;
};
+
+/**
+ * Gets a property and adjusts the value while taking into account indexing.
+ * @param {!Blockly.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}
+ */
+Blockly.Dart.getAdjusted = function(block, atId, opt_delta, opt_negate,
+ opt_order) {
+ var delta = opt_delta || 0;
+ var order = opt_order || Blockly.Dart.ORDER_NONE;
+ if (Blockly.Dart.ONE_BASED_INDEXING) {
+ delta--;
+ }
+ var defaultAtIndex = Blockly.Dart.ONE_BASED_INDEXING ? '1' : '0';
+ if (delta) {
+ var at = Blockly.Dart.valueToCode(block, atId,
+ Blockly.Dart.ORDER_ADDITIVE) || defaultAtIndex;
+ } else if (opt_negate) {
+ var at = Blockly.Dart.valueToCode(block, atId,
+ Blockly.Dart.ORDER_UNARY_PREFIX) || defaultAtIndex;
+ } else {
+ var at = Blockly.Dart.valueToCode(block, atId, order) ||
+ defaultAtIndex;
+ }
+
+ if (Blockly.isNumber(at)) {
+ // If the index is a naked number, adjust it right now.
+ at = parseInt(at, 10) + delta;
+ if (opt_negate) {
+ at = -at;
+ }
+ } else {
+ // If the index is dynamic, adjust it in code.
+ if (delta > 0) {
+ at = at + ' + ' + delta;
+ var innerOrder = Blockly.Dart.ORDER_ADDITIVE;
+ } else if (delta < 0) {
+ at = at + ' - ' + -delta;
+ var innerOrder = Blockly.Dart.ORDER_ADDITIVE;
+ }
+ if (opt_negate) {
+ if (delta) {
+ at = '-(' + at + ')';
+ } else {
+ at = '-' + at;
+ }
+ var innerOrder = Blockly.Dart.ORDER_UNARY_PREFIX;
+ }
+ innerOrder = Math.floor(innerOrder);
+ order = Math.floor(order);
+ if (innerOrder && order >= innerOrder) {
+ at = '(' + at + ')';
+ }
+ }
+ return at;
+};
diff --git a/generators/dart/colour.js b/generators/dart/colour.js
index d73415522..7ded91419 100644
--- a/generators/dart/colour.js
+++ b/generators/dart/colour.js
@@ -43,13 +43,13 @@ Blockly.Dart['colour_random'] = function(block) {
'import \'dart:math\' as Math;';
var functionName = Blockly.Dart.provideFunction_(
'colour_random',
- [ 'String ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ + '() {',
- ' String hex = \'0123456789abcdef\';',
- ' var rnd = new Math.Random();',
- ' return \'#${hex[rnd.nextInt(16)]}${hex[rnd.nextInt(16)]}\'',
- ' \'${hex[rnd.nextInt(16)]}${hex[rnd.nextInt(16)]}\'',
- ' \'${hex[rnd.nextInt(16)]}${hex[rnd.nextInt(16)]}\';',
- '}']);
+ ['String ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ + '() {',
+ ' String hex = \'0123456789abcdef\';',
+ ' var rnd = new Math.Random();',
+ ' return \'#${hex[rnd.nextInt(16)]}${hex[rnd.nextInt(16)]}\'',
+ ' \'${hex[rnd.nextInt(16)]}${hex[rnd.nextInt(16)]}\'',
+ ' \'${hex[rnd.nextInt(16)]}${hex[rnd.nextInt(16)]}\';',
+ '}']);
var code = functionName + '()';
return [code, Blockly.Dart.ORDER_UNARY_POSTFIX];
};
@@ -67,22 +67,22 @@ Blockly.Dart['colour_rgb'] = function(block) {
'import \'dart:math\' as Math;';
var functionName = Blockly.Dart.provideFunction_(
'colour_rgb',
- [ 'String ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ +
+ ['String ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ +
'(num r, num g, num b) {',
- ' num rn = (Math.max(Math.min(r, 1), 0) * 255).round();',
- ' String rs = rn.toInt().toRadixString(16);',
- ' rs = \'0$rs\';',
- ' rs = rs.substring(rs.length - 2);',
- ' num gn = (Math.max(Math.min(g, 1), 0) * 255).round();',
- ' String gs = gn.toInt().toRadixString(16);',
- ' gs = \'0$gs\';',
- ' gs = gs.substring(gs.length - 2);',
- ' num bn = (Math.max(Math.min(b, 1), 0) * 255).round();',
- ' String bs = bn.toInt().toRadixString(16);',
- ' bs = \'0$bs\';',
- ' bs = bs.substring(bs.length - 2);',
- ' return \'#$rs$gs$bs\';',
- '}']);
+ ' num rn = (Math.max(Math.min(r, 1), 0) * 255).round();',
+ ' String rs = rn.toInt().toRadixString(16);',
+ ' rs = \'0$rs\';',
+ ' rs = rs.substring(rs.length - 2);',
+ ' num gn = (Math.max(Math.min(g, 1), 0) * 255).round();',
+ ' String gs = gn.toInt().toRadixString(16);',
+ ' gs = \'0$gs\';',
+ ' gs = gs.substring(gs.length - 2);',
+ ' num bn = (Math.max(Math.min(b, 1), 0) * 255).round();',
+ ' String bs = bn.toInt().toRadixString(16);',
+ ' bs = \'0$bs\';',
+ ' bs = bs.substring(bs.length - 2);',
+ ' return \'#$rs$gs$bs\';',
+ '}']);
var code = functionName + '(' + red + ', ' + green + ', ' + blue + ')';
return [code, Blockly.Dart.ORDER_UNARY_POSTFIX];
};
@@ -100,29 +100,29 @@ Blockly.Dart['colour_blend'] = function(block) {
'import \'dart:math\' as Math;';
var functionName = Blockly.Dart.provideFunction_(
'colour_blend',
- [ 'String ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ +
+ ['String ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ +
'(String c1, String c2, num ratio) {',
- ' ratio = Math.max(Math.min(ratio, 1), 0);',
- ' int r1 = int.parse(\'0x${c1.substring(1, 3)}\');',
- ' int g1 = int.parse(\'0x${c1.substring(3, 5)}\');',
- ' int b1 = int.parse(\'0x${c1.substring(5, 7)}\');',
- ' int r2 = int.parse(\'0x${c2.substring(1, 3)}\');',
- ' int g2 = int.parse(\'0x${c2.substring(3, 5)}\');',
- ' int b2 = int.parse(\'0x${c2.substring(5, 7)}\');',
- ' num rn = (r1 * (1 - ratio) + r2 * ratio).round();',
- ' String rs = rn.toInt().toRadixString(16);',
- ' num gn = (g1 * (1 - ratio) + g2 * ratio).round();',
- ' String gs = gn.toInt().toRadixString(16);',
- ' num bn = (b1 * (1 - ratio) + b2 * ratio).round();',
- ' String bs = bn.toInt().toRadixString(16);',
- ' rs = \'0$rs\';',
- ' rs = rs.substring(rs.length - 2);',
- ' gs = \'0$gs\';',
- ' gs = gs.substring(gs.length - 2);',
- ' bs = \'0$bs\';',
- ' bs = bs.substring(bs.length - 2);',
- ' return \'#$rs$gs$bs\';',
- '}']);
+ ' ratio = Math.max(Math.min(ratio, 1), 0);',
+ ' int r1 = int.parse(\'0x${c1.substring(1, 3)}\');',
+ ' int g1 = int.parse(\'0x${c1.substring(3, 5)}\');',
+ ' int b1 = int.parse(\'0x${c1.substring(5, 7)}\');',
+ ' int r2 = int.parse(\'0x${c2.substring(1, 3)}\');',
+ ' int g2 = int.parse(\'0x${c2.substring(3, 5)}\');',
+ ' int b2 = int.parse(\'0x${c2.substring(5, 7)}\');',
+ ' num rn = (r1 * (1 - ratio) + r2 * ratio).round();',
+ ' String rs = rn.toInt().toRadixString(16);',
+ ' num gn = (g1 * (1 - ratio) + g2 * ratio).round();',
+ ' String gs = gn.toInt().toRadixString(16);',
+ ' num bn = (b1 * (1 - ratio) + b2 * ratio).round();',
+ ' String bs = bn.toInt().toRadixString(16);',
+ ' rs = \'0$rs\';',
+ ' rs = rs.substring(rs.length - 2);',
+ ' gs = \'0$gs\';',
+ ' gs = gs.substring(gs.length - 2);',
+ ' bs = \'0$bs\';',
+ ' bs = bs.substring(bs.length - 2);',
+ ' return \'#$rs$gs$bs\';',
+ '}']);
var code = functionName + '(' + c1 + ', ' + c2 + ', ' + ratio + ')';
return [code, Blockly.Dart.ORDER_UNARY_POSTFIX];
};
diff --git a/generators/dart/lists.js b/generators/dart/lists.js
index 24fcd2243..ae5ecc20e 100644
--- a/generators/dart/lists.js
+++ b/generators/dart/lists.js
@@ -38,49 +38,52 @@ Blockly.Dart['lists_create_empty'] = function(block) {
Blockly.Dart['lists_create_with'] = function(block) {
// Create a list with any number of elements of any type.
- var code = new Array(block.itemCount_);
- for (var n = 0; n < block.itemCount_; n++) {
- code[n] = Blockly.Dart.valueToCode(block, 'ADD' + n,
+ var elements = new Array(block.itemCount_);
+ for (var i = 0; i < block.itemCount_; i++) {
+ elements[i] = Blockly.Dart.valueToCode(block, 'ADD' + i,
Blockly.Dart.ORDER_NONE) || 'null';
}
- code = '[' + code.join(', ') + ']';
+ var code = '[' + elements.join(', ') + ']';
return [code, Blockly.Dart.ORDER_ATOMIC];
};
Blockly.Dart['lists_repeat'] = function(block) {
// Create a list with one element repeated.
- var argument0 = Blockly.Dart.valueToCode(block, 'ITEM',
- Blockly.Dart.ORDER_NONE) || 'null';
- var argument1 = Blockly.Dart.valueToCode(block, 'NUM',
- Blockly.Dart.ORDER_NONE) || '0';
- var code = 'new List.filled(' + argument1 + ', ' + argument0 + ')';
+ var element = Blockly.Dart.valueToCode(block, 'ITEM',
+ Blockly.Dart.ORDER_NONE) || 'null';
+ var repeatCount = Blockly.Dart.valueToCode(block, 'NUM',
+ Blockly.Dart.ORDER_NONE) || '0';
+ var code = 'new List.filled(' + repeatCount + ', ' + element + ')';
return [code, Blockly.Dart.ORDER_UNARY_POSTFIX];
};
Blockly.Dart['lists_length'] = function(block) {
// String or array length.
- var argument0 = Blockly.Dart.valueToCode(block, 'VALUE',
+ var list = Blockly.Dart.valueToCode(block, 'VALUE',
Blockly.Dart.ORDER_UNARY_POSTFIX) || '[]';
- return [argument0 + '.length', Blockly.Dart.ORDER_UNARY_POSTFIX];
+ return [list + '.length', Blockly.Dart.ORDER_UNARY_POSTFIX];
};
Blockly.Dart['lists_isEmpty'] = function(block) {
// Is the string null or array empty?
- var argument0 = Blockly.Dart.valueToCode(block, 'VALUE',
+ var list = Blockly.Dart.valueToCode(block, 'VALUE',
Blockly.Dart.ORDER_UNARY_POSTFIX) || '[]';
- return [argument0 + '.isEmpty', Blockly.Dart.ORDER_UNARY_POSTFIX];
+ return [list + '.isEmpty', Blockly.Dart.ORDER_UNARY_POSTFIX];
};
Blockly.Dart['lists_indexOf'] = function(block) {
// Find an item in the list.
var operator = block.getFieldValue('END') == 'FIRST' ?
'indexOf' : 'lastIndexOf';
- var argument0 = Blockly.Dart.valueToCode(block, 'FIND',
+ var item = Blockly.Dart.valueToCode(block, 'FIND',
Blockly.Dart.ORDER_NONE) || '\'\'';
- var argument1 = Blockly.Dart.valueToCode(block, 'VALUE',
+ var list = Blockly.Dart.valueToCode(block, 'VALUE',
Blockly.Dart.ORDER_UNARY_POSTFIX) || '[]';
- var code = argument1 + '.' + operator + '(' + argument0 + ') + 1';
- return [code, Blockly.Dart.ORDER_ADDITIVE];
+ var code = list + '.' + operator + '(' + item + ')';
+ if (Blockly.Dart.ONE_BASED_INDEXING) {
+ return [code + ' + 1', Blockly.Dart.ORDER_ADDITIVE];
+ }
+ return [code, Blockly.Dart.ORDER_UNARY_POSTFIX];
};
Blockly.Dart['lists_getIndex'] = function(block) {
@@ -88,94 +91,156 @@ Blockly.Dart['lists_getIndex'] = function(block) {
// Note: Until January 2013 this block did not have MODE or WHERE inputs.
var mode = block.getFieldValue('MODE') || 'GET';
var where = block.getFieldValue('WHERE') || 'FROM_START';
- var at = Blockly.Dart.valueToCode(block, 'AT',
- Blockly.Dart.ORDER_UNARY_PREFIX) || '1';
- var list = Blockly.Dart.valueToCode(block, 'VALUE',
- Blockly.Dart.ORDER_UNARY_POSTFIX) || '[]';
+ var listOrder = (where == 'RANDOM' || where == 'FROM_END') ?
+ Blockly.Dart.ORDER_NONE : Blockly.Dart.ORDER_UNARY_POSTFIX;
+ var list = Blockly.Dart.valueToCode(block, 'VALUE', listOrder) || '[]';
+ // Cache non-trivial values to variables to prevent repeated look-ups.
+ // Closure, which accesses and modifies 'list'.
+ function cacheList() {
+ var listVar = Blockly.Dart.variableDB_.getDistinctName(
+ 'tmp_list', Blockly.Variables.NAME_TYPE);
+ var code = 'List ' + listVar + ' = ' + list + ';\n';
+ list = listVar;
+ return code;
+ }
+ // If `list` would be evaluated more than once (which is the case for
+ // RANDOM REMOVE and FROM_END) and is non-trivial, make sure to access it
+ // only once.
+ if (((where == 'RANDOM' && mode == 'REMOVE') || where == 'FROM_END') &&
+ !list.match(/^\w+$/)) {
+ // `list` is an expression, so we may not evaluate it more than once.
+ if (where == 'RANDOM') {
+ Blockly.Dart.definitions_['import_dart_math'] =
+ 'import \'dart:math\' as Math;';
+ // We can use multiple statements.
+ var code = cacheList();
+ var xVar = Blockly.Dart.variableDB_.getDistinctName(
+ 'tmp_x', Blockly.Variables.NAME_TYPE);
+ code += 'int ' + xVar + ' = new Math.Random().nextInt(' + list +
+ '.length);\n';
+ code += list + '.removeAt(' + xVar + ');\n';
+ return code;
+ } else { // where == 'FROM_END'
+ if (mode == 'REMOVE') {
+ // We can use multiple statements.
+ var at = Blockly.Dart.getAdjusted(block, 'AT', 1, false,
+ Blockly.Dart.ORDER_ADDITIVE);
+ var code = cacheList();
+ code += list + '.removeAt(' + list + '.length' + ' - ' + at + ');\n';
+ return code;
- if (where == 'FIRST') {
- if (mode == 'GET') {
- var code = list + '.first';
- return [code, Blockly.Dart.ORDER_UNARY_POSTFIX];
- } else if (mode == 'GET_REMOVE') {
- var code = list + '.removeAt(0)';
- return [code, Blockly.Dart.ORDER_UNARY_POSTFIX];
- } else if (mode == 'REMOVE') {
- return list + '.removeAt(0);\n';
- }
- } else if (where == 'LAST') {
- if (mode == 'GET') {
- var code = list + '.last';
- return [code, Blockly.Dart.ORDER_UNARY_POSTFIX];
- } else if (mode == 'GET_REMOVE') {
- var code = list + '.removeLast()';
- return [code, Blockly.Dart.ORDER_UNARY_POSTFIX];
- } else if (mode == 'REMOVE') {
- return list + '.removeLast();\n';
- }
- } else if (where == 'FROM_START') {
- // Blockly uses one-based indicies.
- if (Blockly.isNumber(at)) {
- // If the index is a naked number, decrement it right now.
- at = parseInt(at, 10) - 1;
- } else {
- // If the index is dynamic, decrement it in code.
- at += ' - 1';
- }
- if (mode == 'GET') {
- var code = list + '[' + at + ']';
- return [code, Blockly.Dart.ORDER_UNARY_POSTFIX];
- } else if (mode == 'GET_REMOVE') {
- var code = list + '.removeAt(' + at + ')';
- return [code, Blockly.Dart.ORDER_UNARY_POSTFIX];
- } else if (mode == 'REMOVE') {
- return list + '.removeAt(' + at + ');\n';
- }
- } else if (where == 'FROM_END') {
- if (mode == 'GET') {
- var functionName = Blockly.Dart.provideFunction_(
- 'lists_get_from_end',
- [ 'dynamic ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ +
- '(List myList, num x) {',
- ' x = myList.length - x;',
- ' return myList.removeAt(x);',
- '}']);
- code = functionName + '(' + list + ', ' + at + ')';
- return [code, Blockly.Dart.ORDER_UNARY_POSTFIX];
- } else if (mode == 'GET_REMOVE' || mode == 'REMOVE') {
- var functionName = Blockly.Dart.provideFunction_(
- 'lists_remove_from_end',
- [ 'dynamic ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ +
- '(List myList, num x) {',
- ' x = myList.length - x;',
- ' return myList.removeAt(x);',
- '}']);
- code = functionName + '(' + list + ', ' + at + ')';
- if (mode == 'GET_REMOVE') {
+ } else if (mode == 'GET') {
+ var at = Blockly.Dart.getAdjusted(block, 'AT', 1);
+ // We need to create a procedure to avoid reevaluating values.
+ var functionName = Blockly.Dart.provideFunction_(
+ 'lists_get_from_end',
+ ['dynamic ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ +
+ '(List my_list, num x) {',
+ ' x = my_list.length - x;',
+ ' return my_list[x];',
+ '}']);
+ var code = functionName + '(' + list + ', ' + at + ')';
+ return [code, Blockly.Dart.ORDER_UNARY_POSTFIX];
+ } else if (mode == 'GET_REMOVE') {
+ var at = Blockly.Dart.getAdjusted(block, 'AT', 1);
+ // We need to create a procedure to avoid reevaluating values.
+ var functionName = Blockly.Dart.provideFunction_(
+ 'lists_remove_from_end',
+ ['dynamic ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ +
+ '(List my_list, num x) {',
+ ' x = my_list.length - x;',
+ ' return my_list.removeAt(x);',
+ '}']);
+ var code = functionName + '(' + list + ', ' + at + ')';
return [code, Blockly.Dart.ORDER_UNARY_POSTFIX];
- } else if (mode == 'REMOVE') {
- return code + ';\n';
}
}
- } else if (where == 'RANDOM') {
- Blockly.Dart.definitions_['import_dart_math'] =
- 'import \'dart:math\' as Math;';
- var functionName = Blockly.Dart.provideFunction_(
- 'lists_get_random_item',
- [ 'dynamic ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ +
- '(List myList, bool remove) {',
- ' int x = new Math.Random().nextInt(myList.length);',
- ' if (remove) {',
- ' return myList.removeAt(x);',
- ' } else {',
- ' return myList[x];',
- ' }',
- '}']);
- code = functionName + '(' + list + ', ' + (mode != 'GET') + ')';
- if (mode == 'GET' || mode == 'GET_REMOVE') {
- return [code, Blockly.Dart.ORDER_UNARY_POSTFIX];
- } else if (mode == 'REMOVE') {
- return code + ';\n';
+ } else {
+ // Either `list` is a simple variable, or we only need to refer to `list`
+ // once.
+ switch (where) {
+ case 'FIRST':
+ if (mode == 'GET') {
+ var code = list + '.first';
+ return [code, Blockly.Dart.ORDER_UNARY_POSTFIX];
+ } else if (mode == 'GET_REMOVE') {
+ var code = list + '.removeAt(0)';
+ return [code, Blockly.Dart.ORDER_UNARY_POSTFIX];
+ } else if (mode == 'REMOVE') {
+ return list + '.removeAt(0);\n';
+ }
+ break;
+ case 'LAST':
+ if (mode == 'GET') {
+ var code = list + '.last';
+ return [code, Blockly.Dart.ORDER_UNARY_POSTFIX];
+ } else if (mode == 'GET_REMOVE') {
+ var code = list + '.removeLast()';
+ return [code, Blockly.Dart.ORDER_UNARY_POSTFIX];
+ } else if (mode == 'REMOVE') {
+ return list + '.removeLast();\n';
+ }
+ break;
+ case 'FROM_START':
+ var at = Blockly.Dart.getAdjusted(block, 'AT');
+ if (mode == 'GET') {
+ var code = list + '[' + at + ']';
+ return [code, Blockly.Dart.ORDER_UNARY_POSTFIX];
+ } else if (mode == 'GET_REMOVE') {
+ var code = list + '.removeAt(' + at + ')';
+ return [code, Blockly.Dart.ORDER_UNARY_POSTFIX];
+ } else if (mode == 'REMOVE') {
+ return list + '.removeAt(' + at + ');\n';
+ }
+ break;
+ case 'FROM_END':
+ var at = Blockly.Dart.getAdjusted(block, 'AT', 1, false,
+ Blockly.Dart.ORDER_ADDITIVE);
+ if (mode == 'GET') {
+ var code = list + '[' + list + '.length - ' + at + ']';
+ return [code, Blockly.Dart.ORDER_UNARY_POSTFIX];
+ } else if (mode == 'GET_REMOVE' || mode == 'REMOVE') {
+ var code = list + '.removeAt(' + list + '.length - ' + at + ')';
+ if (mode == 'GET_REMOVE') {
+ return [code, Blockly.Dart.ORDER_UNARY_POSTFIX];
+ } else if (mode == 'REMOVE') {
+ return code + ';\n';
+ }
+ }
+ break;
+ case 'RANDOM':
+ Blockly.Dart.definitions_['import_dart_math'] =
+ 'import \'dart:math\' as Math;';
+ if (mode == 'REMOVE') {
+ // We can use multiple statements.
+ var xVar = Blockly.Dart.variableDB_.getDistinctName(
+ 'tmp_x', Blockly.Variables.NAME_TYPE);
+ var code = 'int ' + xVar + ' = new Math.Random().nextInt(' + list +
+ '.length);\n';
+ code += list + '.removeAt(' + xVar + ');\n';
+ return code;
+ } else if (mode == 'GET') {
+ var functionName = Blockly.Dart.provideFunction_(
+ 'lists_get_random_item',
+ ['dynamic ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ +
+ '(List my_list) {',
+ ' int x = new Math.Random().nextInt(my_list.length);',
+ ' return my_list[x];',
+ '}']);
+ var code = functionName + '(' + list + ')';
+ return [code, Blockly.Dart.ORDER_UNARY_POSTFIX];
+ } else if (mode == 'GET_REMOVE') {
+ var functionName = Blockly.Dart.provideFunction_(
+ 'lists_remove_random_item',
+ ['dynamic ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ +
+ '(List my_list) {',
+ ' int x = new Math.Random().nextInt(my_list.length);',
+ ' return my_list.removeAt(x);',
+ '}']);
+ var code = functionName + '(' + list + ')';
+ return [code, Blockly.Dart.ORDER_UNARY_POSTFIX];
+ }
+ break;
}
}
throw 'Unhandled combination (lists_getIndex).';
@@ -184,12 +249,10 @@ Blockly.Dart['lists_getIndex'] = function(block) {
Blockly.Dart['lists_setIndex'] = function(block) {
// Set element at index.
// Note: Until February 2013 this block did not have MODE or WHERE inputs.
- var list = Blockly.Dart.valueToCode(block, 'LIST',
- Blockly.Dart.ORDER_UNARY_POSTFIX) || '[]';
var mode = block.getFieldValue('MODE') || 'GET';
var where = block.getFieldValue('WHERE') || 'FROM_START';
- var at = Blockly.Dart.valueToCode(block, 'AT',
- Blockly.Dart.ORDER_ADDITIVE) || '1';
+ var list = Blockly.Dart.valueToCode(block, 'LIST',
+ Blockly.Dart.ORDER_UNARY_POSTFIX) || '[]';
var value = Blockly.Dart.valueToCode(block, 'TO',
Blockly.Dart.ORDER_ASSIGNMENT) || 'null';
// Cache non-trivial values to variables to prevent repeated look-ups.
@@ -204,59 +267,61 @@ Blockly.Dart['lists_setIndex'] = function(block) {
list = listVar;
return code;
}
- if (where == 'FIRST') {
- if (mode == 'SET') {
- return list + '[0] = ' + value + ';\n';
- } else if (mode == 'INSERT') {
- return list + '.insert(0, ' + value + ');\n';
- }
- } else if (where == 'LAST') {
- if (mode == 'SET') {
+ switch (where) {
+ case 'FIRST':
+ if (mode == 'SET') {
+ return list + '[0] = ' + value + ';\n';
+ } else if (mode == 'INSERT') {
+ return list + '.insert(0, ' + value + ');\n';
+ }
+ break;
+ case 'LAST':
+ if (mode == 'SET') {
+ var code = cacheList();
+ code += list + '[' + list + '.length - 1] = ' + value + ';\n';
+ return code;
+ } else if (mode == 'INSERT') {
+ return list + '.add(' + value + ');\n';
+ }
+ break;
+ case 'FROM_START':
+ var at = Blockly.Dart.getAdjusted(block, 'AT');
+ if (mode == 'SET') {
+ return list + '[' + at + '] = ' + value + ';\n';
+ } else if (mode == 'INSERT') {
+ return list + '.insert(' + at + ', ' + value + ');\n';
+ }
+ break;
+ case 'FROM_END':
+ var at = Blockly.Dart.getAdjusted(block, 'AT', 1, false,
+ Blockly.Dart.ORDER_ADDITIVE);
var code = cacheList();
- code += list + '[' + list + '.length - 1] = ' + value + ';\n';
- return code;
- } else if (mode == 'INSERT') {
- return list + '.add(' + value + ');\n';
- }
- } else if (where == 'FROM_START') {
- // Blockly uses one-based indicies.
- if (Blockly.isNumber(at)) {
- // If the index is a naked number, decrement it right now.
- at = parseInt(at, 10) - 1;
- } else {
- // If the index is dynamic, decrement it in code.
- at += ' - 1';
- }
- if (mode == 'SET') {
- return list + '[' + at + '] = ' + value + ';\n';
- } else if (mode == 'INSERT') {
- return list + '.insert(' + at + ', ' + value + ');\n';
- }
- } else if (where == 'FROM_END') {
- var code = cacheList();
- if (mode == 'SET') {
- code += list + '[' + list + '.length - ' + at + '] = ' + value + ';\n';
- return code;
- } else if (mode == 'INSERT') {
- code += list + '.insert(' + list + '.length - ' + at + ', ' +
- value + ');\n';
- return code;
- }
- } else if (where == 'RANDOM') {
- Blockly.Dart.definitions_['import_dart_math'] =
- 'import \'dart:math\' as Math;';
- var code = cacheList();
- var xVar = Blockly.Dart.variableDB_.getDistinctName(
- 'tmp_x', Blockly.Variables.NAME_TYPE);
- code += 'int ' + xVar +
- ' = new Math.Random().nextInt(' + list + '.length);';
- if (mode == 'SET') {
- code += list + '[' + xVar + '] = ' + value + ';\n';
- return code;
- } else if (mode == 'INSERT') {
- code += list + '.insert(' + xVar + ', ' + value + ');\n';
- return code;
- }
+ if (mode == 'SET') {
+ code += list + '[' + list + '.length - ' + at + '] = ' + value +
+ ';\n';
+ return code;
+ } else if (mode == 'INSERT') {
+ code += list + '.insert(' + list + '.length - ' + at + ', ' +
+ value + ');\n';
+ return code;
+ }
+ break;
+ case 'RANDOM':
+ Blockly.Dart.definitions_['import_dart_math'] =
+ 'import \'dart:math\' as Math;';
+ var code = cacheList();
+ var xVar = Blockly.Dart.variableDB_.getDistinctName(
+ 'tmp_x', Blockly.Variables.NAME_TYPE);
+ code += 'int ' + xVar +
+ ' = new Math.Random().nextInt(' + list + '.length);\n';
+ if (mode == 'SET') {
+ code += list + '[' + xVar + '] = ' + value + ';\n';
+ return code;
+ } else if (mode == 'INSERT') {
+ code += list + '.insert(' + xVar + ', ' + value + ');\n';
+ return code;
+ }
+ break;
}
throw 'Unhandled combination (lists_setIndex).';
};
@@ -267,43 +332,67 @@ Blockly.Dart['lists_getSublist'] = function(block) {
Blockly.Dart.ORDER_UNARY_POSTFIX) || '[]';
var where1 = block.getFieldValue('WHERE1');
var where2 = block.getFieldValue('WHERE2');
- var at1 = Blockly.Dart.valueToCode(block, 'AT1',
- Blockly.Dart.ORDER_NONE) || '1';
- var at2 = Blockly.Dart.valueToCode(block, 'AT2',
- Blockly.Dart.ORDER_NONE) || '1';
- if ((where1 == 'FIRST' || where1 == 'FROM_START' && Blockly.isNumber(at1)) &&
- (where2 == 'LAST' || where2 == 'FROM_START' && Blockly.isNumber(at2))) {
- // Simple case that can be done inline.
- at1 = where1 == 'FIRST' ? 0 : parseInt(at1, 10) - 1;
+ if (list.match(/^\w+$/) || (where1 != 'FROM_END' && where2 == 'FROM_START')) {
+ // If the list is a is a variable or doesn't require a call for length,
+ // don't generate a helper function.
+ switch (where1) {
+ case 'FROM_START':
+ var at1 = Blockly.Dart.getAdjusted(block, 'AT1');
+ break;
+ case 'FROM_END':
+ var at1 = Blockly.Dart.getAdjusted(block, 'AT1', 1, false,
+ Blockly.Dart.ORDER_ADDITIVE);
+ at1 = list + '.length - ' + at1;
+ break;
+ case 'FIRST':
+ var at1 = '0';
+ break;
+ default:
+ throw 'Unhandled option (lists_getSublist).';
+ }
+ switch (where2) {
+ case 'FROM_START':
+ var at2 = Blockly.Dart.getAdjusted(block, 'AT2', 1);
+ break;
+ case 'FROM_END':
+ var at2 = Blockly.Dart.getAdjusted(block, 'AT2', 0, false,
+ Blockly.Dart.ORDER_ADDITIVE);
+ at2 = list + '.length - ' + at2;
+ break;
+ case 'LAST':
+ // There is no second index if LAST option is chosen.
+ break;
+ default:
+ throw 'Unhandled option (lists_getSublist).';
+ }
if (where2 == 'LAST') {
- code = list + '.sublist(' + at1 + ')';
+ var code = list + '.sublist(' + at1 + ')';
} else {
- at2 = parseInt(at2, 10);
- code = list + '.sublist(' + at1 + ', ' + at2 + ')';
+ var code = list + '.sublist(' + at1 + ', ' + at2 + ')';
}
} else {
+ var at1 = Blockly.Dart.getAdjusted(block, 'AT1');
+ var at2 = Blockly.Dart.getAdjusted(block, 'AT2');
var functionName = Blockly.Dart.provideFunction_(
'lists_get_sublist',
- [ 'List ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ +
+ ['List ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ +
'(list, where1, at1, where2, at2) {',
- ' int getAt(where, at) {',
- ' if (where == \'FROM_START\') {',
- ' at--;',
- ' } else if (where == \'FROM_END\') {',
- ' at = list.length - at;',
- ' } else if (where == \'FIRST\') {',
- ' at = 0;',
- ' } else if (where == \'LAST\') {',
- ' at = list.length - 1;',
- ' } else {',
- ' throw \'Unhandled option (lists_getSublist).\';',
- ' }',
- ' return at;',
- ' }',
- ' at1 = getAt(where1, at1);',
- ' at2 = getAt(where2, at2) + 1;',
- ' return list.sublist(at1, at2);',
- '}']);
+ ' int getAt(where, at) {',
+ ' if (where == \'FROM_END\') {',
+ ' at = list.length - 1 - at;',
+ ' } else if (where == \'FIRST\') {',
+ ' at = 0;',
+ ' } else if (where == \'LAST\') {',
+ ' at = list.length - 1;',
+ ' } else if (where != \'FROM_START\') {',
+ ' throw \'Unhandled option (lists_getSublist).\';',
+ ' }',
+ ' return at;',
+ ' }',
+ ' at1 = getAt(where1, at1);',
+ ' at2 = getAt(where2, at2) + 1;',
+ ' return list.sublist(at1, at2);',
+ '}']);
var code = functionName + '(' + list + ', \'' +
where1 + '\', ' + at1 + ', \'' + where2 + '\', ' + at2 + ')';
}
@@ -312,51 +401,52 @@ Blockly.Dart['lists_getSublist'] = function(block) {
Blockly.Dart['lists_sort'] = function(block) {
// Block for sorting a list.
- var listCode = Blockly.Dart.valueToCode(block, 'LIST',
- Blockly.Dart.ORDER_UNARY_POSTFIX) || '[]';
+ var list = Blockly.Dart.valueToCode(block, 'LIST',
+ Blockly.Dart.ORDER_NONE) || '[]';
var direction = block.getFieldValue('DIRECTION') === '1' ? 1 : -1;
var type = block.getFieldValue('TYPE');
var sortFunctionName = Blockly.Dart.provideFunction_(
- 'lists_sort',
- ['List ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ +
- '(list, type, direction) {',
- ' var compareFuncs = {',
- ' "NUMERIC": (a, b) => direction * a.compareTo(b),',
- ' "TEXT": (a, b) => direction * a.toString().compareTo(b.toString()),',
- ' "IGNORE_CASE": ',
- ' (a, b) => direction * ',
- ' a.toString().toLowerCase().compareTo(b.toString().toLowerCase())',
- ' };',
- ' list = new List.from(list);', // Clone the list.
- ' var compare = compareFuncs[type];',
- ' list.sort(compare);',
- ' return list;',
- '}']);
- return [sortFunctionName + '(' + listCode + ', ' +
+ 'lists_sort',
+ ['List ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ +
+ '(list, type, direction) {',
+ ' var compareFuncs = {',
+ ' "NUMERIC": (a, b) => direction * a.compareTo(b),',
+ ' "TEXT": (a, b) => direction * ' +
+ 'a.toString().compareTo(b.toString()),',
+ ' "IGNORE_CASE": ',
+ ' (a, b) => direction * ',
+ ' a.toString().toLowerCase().compareTo(b.toString().toLowerCase())',
+ ' };',
+ ' list = new List.from(list);', // Clone the list.
+ ' var compare = compareFuncs[type];',
+ ' list.sort(compare);',
+ ' return list;',
+ '}']);
+ return [sortFunctionName + '(' + list + ', ' +
'"' + type + '", ' + direction + ')',
Blockly.Dart.ORDER_UNARY_POSTFIX];
};
Blockly.Dart['lists_split'] = function(block) {
// Block for splitting text into a list, or joining a list into text.
- var value_input = Blockly.Dart.valueToCode(block, 'INPUT',
+ var input = Blockly.Dart.valueToCode(block, 'INPUT',
Blockly.Dart.ORDER_UNARY_POSTFIX);
- var value_delim = Blockly.Dart.valueToCode(block, 'DELIM',
+ var delimiter = Blockly.Dart.valueToCode(block, 'DELIM',
Blockly.Dart.ORDER_NONE) || '\'\'';
var mode = block.getFieldValue('MODE');
if (mode == 'SPLIT') {
- if (!value_input) {
- value_input = '\'\'';
+ if (!input) {
+ input = '\'\'';
}
var functionName = 'split';
} else if (mode == 'JOIN') {
- if (!value_input) {
- value_input = '[]';
+ if (!input) {
+ input = '[]';
}
var functionName = 'join';
} else {
throw 'Unknown mode: ' + mode;
}
- var code = value_input + '.' + functionName + '(' + value_delim + ')';
+ var code = input + '.' + functionName + '(' + delimiter + ')';
return [code, Blockly.Dart.ORDER_UNARY_POSTFIX];
};
diff --git a/generators/dart/math.js b/generators/dart/math.js
index 2f7c8027a..867822beb 100644
--- a/generators/dart/math.js
+++ b/generators/dart/math.js
@@ -200,25 +200,25 @@ Blockly.Dart['math_number_property'] = function(block) {
'import \'dart:math\' as Math;';
var functionName = Blockly.Dart.provideFunction_(
'math_isPrime',
- [ 'bool ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ + '(n) {',
- ' // https://en.wikipedia.org/wiki/Primality_test#Naive_methods',
- ' if (n == 2 || n == 3) {',
- ' return true;',
- ' }',
- ' // False if n is null, negative, is 1, or not whole.',
- ' // And false if n is divisible by 2 or 3.',
- ' if (n == null || n <= 1 || n % 1 != 0 || n % 2 == 0 ||' +
+ ['bool ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ + '(n) {',
+ ' // https://en.wikipedia.org/wiki/Primality_test#Naive_methods',
+ ' if (n == 2 || n == 3) {',
+ ' return true;',
+ ' }',
+ ' // False if n is null, negative, is 1, or not whole.',
+ ' // And false if n is divisible by 2 or 3.',
+ ' if (n == null || n <= 1 || n % 1 != 0 || n % 2 == 0 ||' +
' n % 3 == 0) {',
- ' return false;',
- ' }',
- ' // Check all the numbers of form 6k +/- 1, up to sqrt(n).',
- ' for (var x = 6; x <= Math.sqrt(n) + 1; x += 6) {',
- ' if (n % (x - 1) == 0 || n % (x + 1) == 0) {',
- ' return false;',
- ' }',
- ' }',
- ' return true;',
- '}']);
+ ' return false;',
+ ' }',
+ ' // Check all the numbers of form 6k +/- 1, up to sqrt(n).',
+ ' for (var x = 6; x <= Math.sqrt(n) + 1; x += 6) {',
+ ' if (n % (x - 1) == 0 || n % (x + 1) == 0) {',
+ ' return false;',
+ ' }',
+ ' }',
+ ' return true;',
+ '}']);
code = functionName + '(' + number_to_check + ')';
return [code, Blockly.Dart.ORDER_UNARY_POSTFIX];
}
@@ -275,12 +275,12 @@ Blockly.Dart['math_on_list'] = function(block) {
case 'SUM':
var functionName = Blockly.Dart.provideFunction_(
'math_sum',
- [ 'num ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ +
+ ['num ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ +
'(List myList) {',
- ' num sumVal = 0;',
- ' myList.forEach((num entry) {sumVal += entry;});',
- ' return sumVal;',
- '}']);
+ ' num sumVal = 0;',
+ ' myList.forEach((num entry) {sumVal += entry;});',
+ ' return sumVal;',
+ '}']);
code = functionName + '(' + list + ')';
break;
case 'MIN':
@@ -288,14 +288,14 @@ Blockly.Dart['math_on_list'] = function(block) {
'import \'dart:math\' as Math;';
var functionName = Blockly.Dart.provideFunction_(
'math_min',
- [ 'num ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ +
+ ['num ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ +
'(List myList) {',
- ' if (myList.isEmpty) return null;',
- ' num minVal = myList[0];',
- ' myList.forEach((num entry) ' +
+ ' if (myList.isEmpty) return null;',
+ ' num minVal = myList[0];',
+ ' myList.forEach((num entry) ' +
'{minVal = Math.min(minVal, entry);});',
- ' return minVal;',
- '}']);
+ ' return minVal;',
+ '}']);
code = functionName + '(' + list + ')';
break;
case 'MAX':
@@ -303,14 +303,14 @@ Blockly.Dart['math_on_list'] = function(block) {
'import \'dart:math\' as Math;';
var functionName = Blockly.Dart.provideFunction_(
'math_max',
- [ 'num ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ +
+ ['num ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ +
'(List myList) {',
- ' if (myList.isEmpty) return null;',
- ' num maxVal = myList[0];',
- ' myList.forEach((num entry) ' +
- '{maxVal = Math.max(maxVal, entry);});',
- ' return maxVal;',
- '}']);
+ ' if (myList.isEmpty) return null;',
+ ' num maxVal = myList[0];',
+ ' myList.forEach((num entry) ' +
+ '{maxVal = Math.max(maxVal, entry);});',
+ ' return maxVal;',
+ '}']);
code = functionName + '(' + list + ')';
break;
case 'AVERAGE':
@@ -318,38 +318,38 @@ Blockly.Dart['math_on_list'] = function(block) {
// math_mean([null,null,"aString",1,9]) == 5.0.
var functionName = Blockly.Dart.provideFunction_(
'math_mean',
- [ 'num ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ +
+ ['num ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ +
'(List myList) {',
- ' // First filter list for numbers only.',
- ' List localList = new List.from(myList);',
- ' localList.removeMatching((a) => a is! num);',
- ' if (localList.isEmpty) return null;',
- ' num sumVal = 0;',
- ' localList.forEach((num entry) {sumVal += entry;});',
- ' return sumVal / localList.length;',
- '}']);
+ ' // First filter list for numbers only.',
+ ' List localList = new List.from(myList);',
+ ' localList.removeWhere((a) => a is! num);',
+ ' if (localList.isEmpty) return null;',
+ ' num sumVal = 0;',
+ ' localList.forEach((num entry) {sumVal += entry;});',
+ ' return sumVal / localList.length;',
+ '}']);
code = functionName + '(' + list + ')';
break;
case 'MEDIAN':
var functionName = Blockly.Dart.provideFunction_(
'math_median',
- [ 'num ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ +
+ ['num ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ +
'(List myList) {',
- ' // First filter list for numbers only, then sort, ' +
+ ' // First filter list for numbers only, then sort, ' +
'then return middle value',
- ' // or the average of two middle values if list has an ' +
+ ' // or the average of two middle values if list has an ' +
'even number of elements.',
- ' List localList = new List.from(myList);',
- ' localList.removeMatching((a) => a is! num);',
- ' if (localList.isEmpty) return null;',
- ' localList.sort((a, b) => (a - b));',
- ' int index = localList.length ~/ 2;',
- ' if (localList.length % 2 == 1) {',
- ' return localList[index];',
- ' } else {',
- ' return (localList[index - 1] + localList[index]) / 2;',
- ' }',
- '}']);
+ ' List localList = new List.from(myList);',
+ ' localList.removeWhere((a) => a is! num);',
+ ' if (localList.isEmpty) return null;',
+ ' localList.sort((a, b) => (a - b));',
+ ' int index = localList.length ~/ 2;',
+ ' if (localList.length % 2 == 1) {',
+ ' return localList[index];',
+ ' } else {',
+ ' return (localList[index - 1] + localList[index]) / 2;',
+ ' }',
+ '}']);
code = functionName + '(' + list + ')';
break;
case 'MODE':
@@ -360,35 +360,35 @@ Blockly.Dart['math_on_list'] = function(block) {
// Mode of [3, 'x', 'x', 1, 1, 2, '3'] -> ['x', 1].
var functionName = Blockly.Dart.provideFunction_(
'math_modes',
- [ 'List ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ +
+ ['List ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ +
'(List values) {',
- ' List modes = [];',
- ' List counts = [];',
- ' int maxCount = 0;',
- ' for (int i = 0; i < values.length; i++) {',
- ' var value = values[i];',
- ' bool found = false;',
- ' int thisCount;',
- ' for (int j = 0; j < counts.length; j++) {',
- ' if (counts[j][0] == value) {',
- ' thisCount = ++counts[j][1];',
- ' found = true;',
- ' break;',
- ' }',
- ' }',
- ' if (!found) {',
- ' counts.add([value, 1]);',
- ' thisCount = 1;',
- ' }',
- ' maxCount = Math.max(thisCount, maxCount);',
- ' }',
- ' for (int j = 0; j < counts.length; j++) {',
- ' if (counts[j][1] == maxCount) {',
- ' modes.add(counts[j][0]);',
- ' }',
- ' }',
- ' return modes;',
- '}']);
+ ' List modes = [];',
+ ' List counts = [];',
+ ' int maxCount = 0;',
+ ' for (int i = 0; i < values.length; i++) {',
+ ' var value = values[i];',
+ ' bool found = false;',
+ ' int thisCount;',
+ ' for (int j = 0; j < counts.length; j++) {',
+ ' if (counts[j][0] == value) {',
+ ' thisCount = ++counts[j][1];',
+ ' found = true;',
+ ' break;',
+ ' }',
+ ' }',
+ ' if (!found) {',
+ ' counts.add([value, 1]);',
+ ' thisCount = 1;',
+ ' }',
+ ' maxCount = Math.max(thisCount, maxCount);',
+ ' }',
+ ' for (int j = 0; j < counts.length; j++) {',
+ ' if (counts[j][1] == maxCount) {',
+ ' modes.add(counts[j][0]);',
+ ' }',
+ ' }',
+ ' return modes;',
+ '}']);
code = functionName + '(' + list + ')';
break;
case 'STD_DEV':
@@ -396,21 +396,21 @@ Blockly.Dart['math_on_list'] = function(block) {
'import \'dart:math\' as Math;';
var functionName = Blockly.Dart.provideFunction_(
'math_standard_deviation',
- [ 'num ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ +
+ ['num ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ +
'(List myList) {',
- ' // First filter list for numbers only.',
- ' List numbers = new List.from(myList);',
- ' numbers.removeMatching((a) => a is! num);',
- ' if (numbers.isEmpty) return null;',
- ' num n = numbers.length;',
- ' num sum = 0;',
- ' numbers.forEach((x) => sum += x);',
- ' num mean = sum / n;',
- ' num sumSquare = 0;',
- ' numbers.forEach((x) => sumSquare += ' +
- 'Math.pow(x - mean, 2));',
- ' return Math.sqrt(sumSquare / n);',
- '}']);
+ ' // First filter list for numbers only.',
+ ' List numbers = new List.from(myList);',
+ ' numbers.removeWhere((a) => a is! num);',
+ ' if (numbers.isEmpty) return null;',
+ ' num n = numbers.length;',
+ ' num sum = 0;',
+ ' numbers.forEach((x) => sum += x);',
+ ' num mean = sum / n;',
+ ' num sumSquare = 0;',
+ ' numbers.forEach((x) => sumSquare += ' +
+ 'Math.pow(x - mean, 2));',
+ ' return Math.sqrt(sumSquare / n);',
+ '}']);
code = functionName + '(' + list + ')';
break;
case 'RANDOM':
@@ -418,11 +418,11 @@ Blockly.Dart['math_on_list'] = function(block) {
'import \'dart:math\' as Math;';
var functionName = Blockly.Dart.provideFunction_(
'math_random_item',
- [ 'dynamic ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ +
+ ['dynamic ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ +
'(List myList) {',
- ' int x = new Math.Random().nextInt(myList.length);',
- ' return myList[x];',
- '}']);
+ ' int x = new Math.Random().nextInt(myList.length);',
+ ' return myList[x];',
+ '}']);
code = functionName + '(' + list + ')';
break;
default:
@@ -466,15 +466,15 @@ Blockly.Dart['math_random_int'] = function(block) {
Blockly.Dart.ORDER_NONE) || '0';
var functionName = Blockly.Dart.provideFunction_(
'math_random_int',
- [ 'int ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ + '(num a, num b) {',
- ' if (a > b) {',
- ' // Swap a and b to ensure a is smaller.',
- ' num c = a;',
- ' a = b;',
- ' b = c;',
- ' }',
- ' return new Math.Random().nextInt(b - a + 1) + a;',
- '}']);
+ ['int ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ + '(num a, num b) {',
+ ' if (a > b) {',
+ ' // Swap a and b to ensure a is smaller.',
+ ' num c = a;',
+ ' a = b;',
+ ' b = c;',
+ ' }',
+ ' return new Math.Random().nextInt(b - a + 1) + a;',
+ '}']);
var code = functionName + '(' + argument0 + ', ' + argument1 + ')';
return [code, Blockly.Dart.ORDER_UNARY_POSTFIX];
};
diff --git a/generators/dart/procedures.js b/generators/dart/procedures.js
index 0085c6bf6..ad2550cc7 100644
--- a/generators/dart/procedures.js
+++ b/generators/dart/procedures.js
@@ -50,8 +50,8 @@ Blockly.Dart['procedures_defreturn'] = function(block) {
}
var returnType = returnValue ? 'dynamic' : 'void';
var args = [];
- for (var x = 0; x < block.arguments_.length; x++) {
- args[x] = Blockly.Dart.variableDB_.getName(block.arguments_[x],
+ for (var i = 0; i < block.arguments_.length; i++) {
+ args[i] = Blockly.Dart.variableDB_.getName(block.arguments_[i],
Blockly.Variables.NAME_TYPE);
}
var code = returnType + ' ' + funcName + '(' + args.join(', ') + ') {\n' +
@@ -71,8 +71,8 @@ Blockly.Dart['procedures_callreturn'] = function(block) {
var funcName = Blockly.Dart.variableDB_.getName(block.getFieldValue('NAME'),
Blockly.Procedures.NAME_TYPE);
var args = [];
- for (var x = 0; x < block.arguments_.length; x++) {
- args[x] = Blockly.Dart.valueToCode(block, 'ARG' + x,
+ for (var i = 0; i < block.arguments_.length; i++) {
+ args[i] = Blockly.Dart.valueToCode(block, 'ARG' + i,
Blockly.Dart.ORDER_NONE) || 'null';
}
var code = funcName + '(' + args.join(', ') + ')';
@@ -84,8 +84,8 @@ Blockly.Dart['procedures_callnoreturn'] = function(block) {
var funcName = Blockly.Dart.variableDB_.getName(block.getFieldValue('NAME'),
Blockly.Procedures.NAME_TYPE);
var args = [];
- for (var x = 0; x < block.arguments_.length; x++) {
- args[x] = Blockly.Dart.valueToCode(block, 'ARG' + x,
+ for (var i = 0; i < block.arguments_.length; i++) {
+ args[i] = Blockly.Dart.valueToCode(block, 'ARG' + i,
Blockly.Dart.ORDER_NONE) || 'null';
}
var code = funcName + '(' + args.join(', ') + ');\n';
diff --git a/generators/dart/text.js b/generators/dart/text.js
index ba5a75cb0..5cdbb03ec 100644
--- a/generators/dart/text.js
+++ b/generators/dart/text.js
@@ -39,22 +39,22 @@ Blockly.Dart['text'] = function(block) {
Blockly.Dart['text_join'] = function(block) {
// Create a string made up of any number of elements of any type.
- var code;
- if (block.itemCount_ == 0) {
- return ['\'\'', Blockly.Dart.ORDER_ATOMIC];
- } else if (block.itemCount_ == 1) {
- var argument0 = Blockly.Dart.valueToCode(block, 'ADD0',
- Blockly.Dart.ORDER_UNARY_POSTFIX) || '\'\'';
- code = argument0 + '.toString()';
- return [code, Blockly.Dart.ORDER_UNARY_POSTFIX];
- } else {
- code = new Array(block.itemCount_);
- for (var n = 0; n < block.itemCount_; n++) {
- code[n] = Blockly.Dart.valueToCode(block, 'ADD' + n,
- Blockly.Dart.ORDER_NONE) || '\'\'';
- }
- code = '[' + code.join(',') + '].join()';
- return [code, Blockly.Dart.ORDER_UNARY_POSTFIX];
+ switch (block.itemCount_) {
+ case 0:
+ return ['\'\'', Blockly.Dart.ORDER_ATOMIC];
+ case 1:
+ var element = Blockly.Dart.valueToCode(block, 'ADD0',
+ Blockly.Dart.ORDER_UNARY_POSTFIX) || '\'\'';
+ var code = element + '.toString()';
+ return [code, Blockly.Dart.ORDER_UNARY_POSTFIX];
+ default:
+ var elements = new Array(block.itemCount_);
+ for (var i = 0; i < block.itemCount_; i++) {
+ elements[i] = Blockly.Dart.valueToCode(block, 'ADD' + i,
+ Blockly.Dart.ORDER_NONE) || '\'\'';
+ }
+ var code = '[' + elements.join(',') + '].join()';
+ return [code, Blockly.Dart.ORDER_UNARY_POSTFIX];
}
};
@@ -62,43 +62,44 @@ Blockly.Dart['text_append'] = function(block) {
// Append to a variable in place.
var varName = Blockly.Dart.variableDB_.getName(block.getFieldValue('VAR'),
Blockly.Variables.NAME_TYPE);
- var argument0 = Blockly.Dart.valueToCode(block, 'TEXT',
- Blockly.Dart.ORDER_UNARY_POSTFIX) || '\'\'';
- return varName + ' = [' + varName + ', ' + argument0 + '].join();\n';
+ var value = Blockly.Dart.valueToCode(block, 'TEXT',
+ Blockly.Dart.ORDER_NONE) || '\'\'';
+ return varName + ' = [' + varName + ', ' + value + '].join();\n';
};
Blockly.Dart['text_length'] = function(block) {
// String or array length.
- var argument0 = Blockly.Dart.valueToCode(block, 'VALUE',
+ var text = Blockly.Dart.valueToCode(block, 'VALUE',
Blockly.Dart.ORDER_UNARY_POSTFIX) || '\'\'';
- return [argument0 + '.length', Blockly.Dart.ORDER_UNARY_POSTFIX];
+ return [text + '.length', Blockly.Dart.ORDER_UNARY_POSTFIX];
};
Blockly.Dart['text_isEmpty'] = function(block) {
// Is the string null or array empty?
- var argument0 = Blockly.Dart.valueToCode(block, 'VALUE',
+ var text = Blockly.Dart.valueToCode(block, 'VALUE',
Blockly.Dart.ORDER_UNARY_POSTFIX) || '\'\'';
- return [argument0 + '.isEmpty', Blockly.Dart.ORDER_UNARY_POSTFIX];
+ return [text + '.isEmpty', Blockly.Dart.ORDER_UNARY_POSTFIX];
};
Blockly.Dart['text_indexOf'] = function(block) {
// Search the text for a substring.
var operator = block.getFieldValue('END') == 'FIRST' ?
'indexOf' : 'lastIndexOf';
- var argument0 = Blockly.Dart.valueToCode(block, 'FIND',
+ var substring = Blockly.Dart.valueToCode(block, 'FIND',
Blockly.Dart.ORDER_NONE) || '\'\'';
- var argument1 = Blockly.Dart.valueToCode(block, 'VALUE',
+ var text = Blockly.Dart.valueToCode(block, 'VALUE',
Blockly.Dart.ORDER_UNARY_POSTFIX) || '\'\'';
- var code = argument1 + '.' + operator + '(' + argument0 + ') + 1';
- return [code, Blockly.Dart.ORDER_ADDITIVE];
+ var code = text + '.' + operator + '(' + substring + ')';
+ if (Blockly.Dart.ONE_BASED_INDEXING) {
+ return [code + ' + 1', Blockly.Dart.ORDER_ADDITIVE];
+ }
+ return [code, Blockly.Dart.ORDER_UNARY_POSTFIX];
};
Blockly.Dart['text_charAt'] = function(block) {
// Get letter at index.
// Note: Until January 2013 this block did not have the WHERE input.
var where = block.getFieldValue('WHERE') || 'FROM_START';
- var at = Blockly.Dart.valueToCode(block, 'AT',
- Blockly.Dart.ORDER_NONE) || '1';
var text = Blockly.Dart.valueToCode(block, 'VALUE',
Blockly.Dart.ORDER_UNARY_POSTFIX) || '\'\'';
switch (where) {
@@ -106,26 +107,20 @@ Blockly.Dart['text_charAt'] = function(block) {
var code = text + '[0]';
return [code, Blockly.Dart.ORDER_UNARY_POSTFIX];
case 'FROM_START':
- // Blockly uses one-based indicies.
- if (at.match(/^-?\d+$/)) {
- // If the index is a naked number, decrement it right now.
- at = parseInt(at, 10) - 1;
- } else {
- // If the index is dynamic, decrement it in code.
- at += ' - 1';
- }
+ var at = Blockly.Dart.getAdjusted(block, 'AT');
var code = text + '[' + at + ']';
return [code, Blockly.Dart.ORDER_UNARY_POSTFIX];
case 'LAST':
at = 1;
// Fall through.
case 'FROM_END':
+ var at = Blockly.Dart.getAdjusted(block, 'AT', 1);
var functionName = Blockly.Dart.provideFunction_(
'text_get_from_end',
- [ 'String ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ +
+ ['String ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ +
'(String text, num x) {',
- ' return text[text.length - x];',
- '}']);
+ ' return text[text.length - x];',
+ '}']);
code = functionName + '(' + text + ', ' + at + ')';
return [code, Blockly.Dart.ORDER_UNARY_POSTFIX];
case 'RANDOM':
@@ -133,11 +128,11 @@ Blockly.Dart['text_charAt'] = function(block) {
'import \'dart:math\' as Math;';
var functionName = Blockly.Dart.provideFunction_(
'text_random_letter',
- [ 'String ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ +
+ ['String ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ +
'(String text) {',
- ' int x = new Math.Random().nextInt(text.length);',
- ' return text[x];',
- '}']);
+ ' int x = new Math.Random().nextInt(text.length);',
+ ' return text[x];',
+ '}']);
code = functionName + '(' + text + ')';
return [code, Blockly.Dart.ORDER_UNARY_POSTFIX];
}
@@ -150,35 +145,69 @@ Blockly.Dart['text_getSubstring'] = function(block) {
Blockly.Dart.ORDER_UNARY_POSTFIX) || '\'\'';
var where1 = block.getFieldValue('WHERE1');
var where2 = block.getFieldValue('WHERE2');
- var at1 = Blockly.Dart.valueToCode(block, 'AT1',
- Blockly.Dart.ORDER_NONE) || '1';
- var at2 = Blockly.Dart.valueToCode(block, 'AT2',
- Blockly.Dart.ORDER_NONE) || '1';
if (where1 == 'FIRST' && where2 == 'LAST') {
var code = text;
+ } else if (text.match(/^'?\w+'?$/) ||
+ (where1 != 'FROM_END' && where2 == 'FROM_START')) {
+ // If the text is a variable or literal or doesn't require a call for
+ // length, don't generate a helper function.
+ switch (where1) {
+ case 'FROM_START':
+ var at1 = Blockly.Dart.getAdjusted(block, 'AT1');
+ break;
+ case 'FROM_END':
+ var at1 = Blockly.Dart.getAdjusted(block, 'AT1', 1, false,
+ Blockly.Dart.ORDER_ADDITIVE);
+ at1 = text + '.length - ' + at1;
+ break;
+ case 'FIRST':
+ var at1 = '0';
+ break;
+ default:
+ throw 'Unhandled option (text_getSubstring).';
+ }
+ switch (where2) {
+ case 'FROM_START':
+ var at2 = Blockly.Dart.getAdjusted(block, 'AT2', 1);
+ break;
+ case 'FROM_END':
+ var at2 = Blockly.Dart.getAdjusted(block, 'AT2', 0, false,
+ Blockly.Dart.ORDER_ADDITIVE);
+ at2 = text + '.length - ' + at2;
+ break;
+ case 'LAST':
+ break;
+ default:
+ throw 'Unhandled option (text_getSubstring).';
+ }
+ if (where2 == 'LAST') {
+ var code = text + '.substring(' + at1 + ')';
+ } else {
+ var code = text + '.substring(' + at1 + ', ' + at2 + ')';
+ }
} else {
+ var at1 = Blockly.Dart.getAdjusted(block, 'AT1');
+ var at2 = Blockly.Dart.getAdjusted(block, 'AT2');
var functionName = Blockly.Dart.provideFunction_(
'text_get_substring',
- [ 'function ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ +
+ ['List ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ +
'(text, where1, at1, where2, at2) {',
- ' function getAt(where, at) {',
- ' if (where == \'FROM_START\') {',
- ' at--;',
- ' } else if (where == \'FROM_END\') {',
- ' at = text.length - at;',
- ' } else if (where == \'FIRST\') {',
- ' at = 0;',
- ' } else if (where == \'LAST\') {',
- ' at = text.length - 1;',
- ' } else {',
- ' throw \'Unhandled option (text_getSubstring).\';',
- ' }',
- ' return at;',
- ' }',
- ' at1 = getAt(where1, at1);',
- ' at2 = getAt(where2, at2) + 1;',
- ' return text.substring(at1, at2);',
- '}']);
+ ' int getAt(where, at) {',
+ ' if (where == \'FROM_END\') {',
+ ' at = text.length - 1 - at;',
+ ' } else if (where == \'FIRST\') {',
+ ' at = 0;',
+ ' } else if (where == \'LAST\') {',
+ ' at = text.length - 1;',
+ ' } else if (where != \'FROM_START\') {',
+ ' throw \'Unhandled option (text_getSubstring).\';',
+ ' }',
+ ' return at;',
+ ' }',
+ ' at1 = getAt(where1, at1);',
+ ' at2 = getAt(where2, at2) + 1;',
+ ' return text.substring(at1, at2);',
+ '}']);
var code = functionName + '(' + text + ', \'' +
where1 + '\', ' + at1 + ', \'' + where2 + '\', ' + at2 + ')';
}
@@ -193,34 +222,32 @@ Blockly.Dart['text_changeCase'] = function(block) {
'TITLECASE': null
};
var operator = OPERATORS[block.getFieldValue('CASE')];
- var code;
+ var textOrder = operator ? Blockly.Dart.ORDER_UNARY_POSTFIX :
+ Blockly.Dart.ORDER_NONE;
+ var text = Blockly.Dart.valueToCode(block, 'TEXT', textOrder) || '\'\'';
if (operator) {
// Upper and lower case are functions built into Dart.
- var argument0 = Blockly.Dart.valueToCode(block, 'TEXT',
- Blockly.Dart.ORDER_UNARY_POSTFIX) || '\'\'';
- code = argument0 + operator;
+ var code = text + operator;
} else {
// Title case is not a native Dart function. Define one.
var functionName = Blockly.Dart.provideFunction_(
'text_toTitleCase',
- [ 'String ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ +
+ ['String ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ +
'(String str) {',
- ' RegExp exp = new RegExp(r\'\\b\');',
- ' List list = str.split(exp);',
- ' final title = new StringBuffer();',
- ' for (String part in list) {',
- ' if (part.length > 0) {',
- ' title.write(part[0].toUpperCase());',
- ' if (part.length > 0) {',
- ' title.write(part.substring(1).toLowerCase());',
- ' }',
- ' }',
- ' }',
- ' return title.toString();',
- '}']);
- var argument0 = Blockly.Dart.valueToCode(block, 'TEXT',
- Blockly.Dart.ORDER_NONE) || '\'\'';
- code = functionName + '(' + argument0 + ')';
+ ' RegExp exp = new RegExp(r\'\\b\');',
+ ' List list = str.split(exp);',
+ ' final title = new StringBuffer();',
+ ' for (String part in list) {',
+ ' if (part.length > 0) {',
+ ' title.write(part[0].toUpperCase());',
+ ' if (part.length > 0) {',
+ ' title.write(part.substring(1).toLowerCase());',
+ ' }',
+ ' }',
+ ' }',
+ ' return title.toString();',
+ '}']);
+ var code = functionName + '(' + text + ')';
}
return [code, Blockly.Dart.ORDER_UNARY_POSTFIX];
};
@@ -233,16 +260,16 @@ Blockly.Dart['text_trim'] = function(block) {
'BOTH': '.trim()'
};
var operator = OPERATORS[block.getFieldValue('MODE')];
- var argument0 = Blockly.Dart.valueToCode(block, 'TEXT',
+ var text = Blockly.Dart.valueToCode(block, 'TEXT',
Blockly.Dart.ORDER_UNARY_POSTFIX) || '\'\'';
- return [argument0 + operator, Blockly.Dart.ORDER_UNARY_POSTFIX];
+ return [text + operator, Blockly.Dart.ORDER_UNARY_POSTFIX];
};
Blockly.Dart['text_print'] = function(block) {
// Print statement.
- var argument0 = Blockly.Dart.valueToCode(block, 'TEXT',
+ var msg = Blockly.Dart.valueToCode(block, 'TEXT',
Blockly.Dart.ORDER_NONE) || '\'\'';
- return 'print(' + argument0 + ');\n';
+ return 'print(' + msg + ');\n';
};
Blockly.Dart['text_prompt_ext'] = function(block) {
diff --git a/generators/javascript.js b/generators/javascript.js
index dcd1f146d..a81b62b0c 100644
--- a/generators/javascript.js
+++ b/generators/javascript.js
@@ -135,8 +135,8 @@ Blockly.JavaScript.ORDER_OVERRIDES = [
];
/**
- * Allow for switching between one and zero based indexing, one based by
- * default.
+ * Allow for switching between one and zero based indexing for lists and text,
+ * one based by default.
*/
Blockly.JavaScript.ONE_BASED_INDEXING = true;
@@ -258,3 +258,66 @@ Blockly.JavaScript.scrub_ = function(block, code) {
var nextCode = Blockly.JavaScript.blockToCode(nextBlock);
return commentCode + code + nextCode;
};
+
+/**
+ * Gets a property and adjusts the value while taking into account indexing.
+ * @param {!Blockly.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}
+ */
+Blockly.JavaScript.getAdjusted = function(block, atId, opt_delta, opt_negate,
+ opt_order) {
+ var delta = opt_delta || 0;
+ var order = opt_order || Blockly.JavaScript.ORDER_NONE;
+ if (Blockly.JavaScript.ONE_BASED_INDEXING) {
+ delta--;
+ }
+ var defaultAtIndex = Blockly.JavaScript.ONE_BASED_INDEXING ? '1' : '0';
+ if (delta > 0) {
+ var at = Blockly.JavaScript.valueToCode(block, atId,
+ Blockly.JavaScript.ORDER_ADDITION) || defaultAtIndex;
+ } else if (delta < 0) {
+ var at = Blockly.JavaScript.valueToCode(block, atId,
+ Blockly.JavaScript.ORDER_SUBTRACTION) || defaultAtIndex;
+ } else if (opt_negate) {
+ var at = Blockly.JavaScript.valueToCode(block, atId,
+ Blockly.JavaScript.ORDER_UNARY_NEGATION) || defaultAtIndex;
+ } else {
+ var at = Blockly.JavaScript.valueToCode(block, atId, order) ||
+ defaultAtIndex;
+ }
+
+ if (Blockly.isNumber(at)) {
+ // If the index is a naked number, adjust it right now.
+ at = parseFloat(at) + delta;
+ if (opt_negate) {
+ at = -at;
+ }
+ } else {
+ // If the index is dynamic, adjust it in code.
+ if (delta > 0) {
+ at = at + ' + ' + delta;
+ var innerOrder = Blockly.JavaScript.ORDER_ADDITION;
+ } else if (delta < 0) {
+ at = at + ' - ' + -delta;
+ var innerOrder = Blockly.JavaScript.ORDER_SUBTRACTION;
+ }
+ if (opt_negate) {
+ if (delta) {
+ at = '-(' + at + ')';
+ } else {
+ at = '-' + at;
+ }
+ var innerOrder = Blockly.JavaScript.ORDER_UNARY_NEGATION;
+ }
+ innerOrder = Math.floor(innerOrder);
+ order = Math.floor(order);
+ if (innerOrder && order >= innerOrder) {
+ at = '(' + at + ')';
+ }
+ }
+ return at;
+};
diff --git a/generators/javascript/colour.js b/generators/javascript/colour.js
index b8e290360..21b372e9c 100644
--- a/generators/javascript/colour.js
+++ b/generators/javascript/colour.js
@@ -39,7 +39,7 @@ Blockly.JavaScript['colour_random'] = function(block) {
// Generate a random colour.
var functionName = Blockly.JavaScript.provideFunction_(
'colourRandom',
- [ 'function ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ + '() {',
+ ['function ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ + '() {',
' var num = Math.floor(Math.random() * Math.pow(2, 24));',
' return \'#\' + (\'00000\' + num.toString(16)).substr(-6);',
'}']);
@@ -57,16 +57,16 @@ Blockly.JavaScript['colour_rgb'] = function(block) {
Blockly.JavaScript.ORDER_COMMA) || 0;
var functionName = Blockly.JavaScript.provideFunction_(
'colourRgb',
- [ 'function ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ +
+ ['function ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ +
'(r, g, b) {',
- ' r = Math.max(Math.min(Number(r), 100), 0) * 2.55;',
- ' g = Math.max(Math.min(Number(g), 100), 0) * 2.55;',
- ' b = Math.max(Math.min(Number(b), 100), 0) * 2.55;',
- ' r = (\'0\' + (Math.round(r) || 0).toString(16)).slice(-2);',
- ' g = (\'0\' + (Math.round(g) || 0).toString(16)).slice(-2);',
- ' b = (\'0\' + (Math.round(b) || 0).toString(16)).slice(-2);',
- ' return \'#\' + r + g + b;',
- '}']);
+ ' r = Math.max(Math.min(Number(r), 100), 0) * 2.55;',
+ ' g = Math.max(Math.min(Number(g), 100), 0) * 2.55;',
+ ' b = Math.max(Math.min(Number(b), 100), 0) * 2.55;',
+ ' r = (\'0\' + (Math.round(r) || 0).toString(16)).slice(-2);',
+ ' g = (\'0\' + (Math.round(g) || 0).toString(16)).slice(-2);',
+ ' b = (\'0\' + (Math.round(b) || 0).toString(16)).slice(-2);',
+ ' return \'#\' + r + g + b;',
+ '}']);
var code = functionName + '(' + red + ', ' + green + ', ' + blue + ')';
return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL];
};
@@ -81,23 +81,23 @@ Blockly.JavaScript['colour_blend'] = function(block) {
Blockly.JavaScript.ORDER_COMMA) || 0.5;
var functionName = Blockly.JavaScript.provideFunction_(
'colourBlend',
- [ 'function ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ +
+ ['function ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ +
'(c1, c2, ratio) {',
- ' ratio = Math.max(Math.min(Number(ratio), 1), 0);',
- ' var r1 = parseInt(c1.substring(1, 3), 16);',
- ' var g1 = parseInt(c1.substring(3, 5), 16);',
- ' var b1 = parseInt(c1.substring(5, 7), 16);',
- ' var r2 = parseInt(c2.substring(1, 3), 16);',
- ' var g2 = parseInt(c2.substring(3, 5), 16);',
- ' var b2 = parseInt(c2.substring(5, 7), 16);',
- ' var r = Math.round(r1 * (1 - ratio) + r2 * ratio);',
- ' var g = Math.round(g1 * (1 - ratio) + g2 * ratio);',
- ' var b = Math.round(b1 * (1 - ratio) + b2 * ratio);',
- ' r = (\'0\' + (r || 0).toString(16)).slice(-2);',
- ' g = (\'0\' + (g || 0).toString(16)).slice(-2);',
- ' b = (\'0\' + (b || 0).toString(16)).slice(-2);',
- ' return \'#\' + r + g + b;',
- '}']);
+ ' ratio = Math.max(Math.min(Number(ratio), 1), 0);',
+ ' var r1 = parseInt(c1.substring(1, 3), 16);',
+ ' var g1 = parseInt(c1.substring(3, 5), 16);',
+ ' var b1 = parseInt(c1.substring(5, 7), 16);',
+ ' var r2 = parseInt(c2.substring(1, 3), 16);',
+ ' var g2 = parseInt(c2.substring(3, 5), 16);',
+ ' var b2 = parseInt(c2.substring(5, 7), 16);',
+ ' var r = Math.round(r1 * (1 - ratio) + r2 * ratio);',
+ ' var g = Math.round(g1 * (1 - ratio) + g2 * ratio);',
+ ' var b = Math.round(b1 * (1 - ratio) + b2 * ratio);',
+ ' r = (\'0\' + (r || 0).toString(16)).slice(-2);',
+ ' g = (\'0\' + (g || 0).toString(16)).slice(-2);',
+ ' b = (\'0\' + (b || 0).toString(16)).slice(-2);',
+ ' return \'#\' + r + g + b;',
+ '}']);
var code = functionName + '(' + c1 + ', ' + c2 + ', ' + ratio + ')';
return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL];
};
diff --git a/generators/javascript/lists.js b/generators/javascript/lists.js
index 4bb6aac20..d1e66a0ed 100644
--- a/generators/javascript/lists.js
+++ b/generators/javascript/lists.js
@@ -36,12 +36,12 @@ Blockly.JavaScript['lists_create_empty'] = function(block) {
Blockly.JavaScript['lists_create_with'] = function(block) {
// Create a list with any number of elements of any type.
- var code = new Array(block.itemCount_);
- for (var n = 0; n < block.itemCount_; n++) {
- code[n] = Blockly.JavaScript.valueToCode(block, 'ADD' + n,
+ var elements = new Array(block.itemCount_);
+ for (var i = 0; i < block.itemCount_; i++) {
+ elements[i] = Blockly.JavaScript.valueToCode(block, 'ADD' + i,
Blockly.JavaScript.ORDER_COMMA) || 'null';
}
- code = '[' + code.join(', ') + ']';
+ var code = '[' + elements.join(', ') + ']';
return [code, Blockly.JavaScript.ORDER_ATOMIC];
};
@@ -49,46 +49,49 @@ Blockly.JavaScript['lists_repeat'] = function(block) {
// Create a list with one element repeated.
var functionName = Blockly.JavaScript.provideFunction_(
'listsRepeat',
- [ 'function ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ +
+ ['function ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ +
'(value, n) {',
- ' var array = [];',
- ' for (var i = 0; i < n; i++) {',
- ' array[i] = value;',
- ' }',
- ' return array;',
- '}']);
- var argument0 = Blockly.JavaScript.valueToCode(block, 'ITEM',
+ ' var array = [];',
+ ' for (var i = 0; i < n; i++) {',
+ ' array[i] = value;',
+ ' }',
+ ' return array;',
+ '}']);
+ var element = Blockly.JavaScript.valueToCode(block, 'ITEM',
Blockly.JavaScript.ORDER_COMMA) || 'null';
- var argument1 = Blockly.JavaScript.valueToCode(block, 'NUM',
+ var repeatCount = Blockly.JavaScript.valueToCode(block, 'NUM',
Blockly.JavaScript.ORDER_COMMA) || '0';
- var code = functionName + '(' + argument0 + ', ' + argument1 + ')';
+ var code = functionName + '(' + element + ', ' + repeatCount + ')';
return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL];
};
Blockly.JavaScript['lists_length'] = function(block) {
// String or array length.
- var argument0 = Blockly.JavaScript.valueToCode(block, 'VALUE',
- Blockly.JavaScript.ORDER_FUNCTION_CALL) || '[]';
- return [argument0 + '.length', Blockly.JavaScript.ORDER_MEMBER];
+ var list = Blockly.JavaScript.valueToCode(block, 'VALUE',
+ Blockly.JavaScript.ORDER_MEMBER) || '[]';
+ return [list + '.length', Blockly.JavaScript.ORDER_MEMBER];
};
Blockly.JavaScript['lists_isEmpty'] = function(block) {
// Is the string null or array empty?
- var argument0 = Blockly.JavaScript.valueToCode(block, 'VALUE',
+ var list = Blockly.JavaScript.valueToCode(block, 'VALUE',
Blockly.JavaScript.ORDER_MEMBER) || '[]';
- return ['!' + argument0 + '.length', Blockly.JavaScript.ORDER_LOGICAL_NOT];
+ return ['!' + list + '.length', Blockly.JavaScript.ORDER_LOGICAL_NOT];
};
Blockly.JavaScript['lists_indexOf'] = function(block) {
// Find an item in the list.
var operator = block.getFieldValue('END') == 'FIRST' ?
'indexOf' : 'lastIndexOf';
- var argument0 = Blockly.JavaScript.valueToCode(block, 'FIND',
+ var item = Blockly.JavaScript.valueToCode(block, 'FIND',
Blockly.JavaScript.ORDER_NONE) || '\'\'';
- var argument1 = Blockly.JavaScript.valueToCode(block, 'VALUE',
+ var list = Blockly.JavaScript.valueToCode(block, 'VALUE',
Blockly.JavaScript.ORDER_MEMBER) || '[]';
- var code = argument1 + '.' + operator + '(' + argument0 + ') + 1';
- return [code, Blockly.JavaScript.ORDER_ADDITION];
+ var code = list + '.' + operator + '(' + item + ')';
+ if (Blockly.JavaScript.ONE_BASED_INDEXING) {
+ return [code + ' + 1', Blockly.JavaScript.ORDER_ADDITION];
+ }
+ return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL];
};
Blockly.JavaScript['lists_getIndex'] = function(block) {
@@ -96,86 +99,76 @@ Blockly.JavaScript['lists_getIndex'] = function(block) {
// Note: Until January 2013 this block did not have MODE or WHERE inputs.
var mode = block.getFieldValue('MODE') || 'GET';
var where = block.getFieldValue('WHERE') || 'FROM_START';
- var at = Blockly.JavaScript.valueToCode(block, 'AT',
- Blockly.JavaScript.ORDER_UNARY_NEGATION) || '1';
- var list = Blockly.JavaScript.valueToCode(block, 'VALUE',
- Blockly.JavaScript.ORDER_MEMBER) || '[]';
+ var listOrder = (where == 'RANDOM') ? Blockly.JavaScript.ORDER_COMMA :
+ Blockly.JavaScript.ORDER_MEMBER;
+ var list = Blockly.JavaScript.valueToCode(block, 'VALUE', listOrder) || '[]';
- if (where == 'FIRST') {
- if (mode == 'GET') {
- var code = list + '[0]';
- return [code, Blockly.JavaScript.ORDER_MEMBER];
- } else if (mode == 'GET_REMOVE') {
- var code = list + '.shift()';
- return [code, Blockly.JavaScript.ORDER_MEMBER];
- } else if (mode == 'REMOVE') {
- return list + '.shift();\n';
- }
- } else if (where == 'LAST') {
- if (mode == 'GET') {
- var code = list + '.slice(-1)[0]';
- return [code, Blockly.JavaScript.ORDER_MEMBER];
- } else if (mode == 'GET_REMOVE') {
- var code = list + '.pop()';
- return [code, Blockly.JavaScript.ORDER_MEMBER];
- } else if (mode == 'REMOVE') {
- return list + '.pop();\n';
- }
- } else if (where == 'FROM_START') {
- // Blockly uses one-based indicies.
- if (Blockly.isNumber(at)) {
- // If the index is a naked number, decrement it right now.
- at = parseFloat(at) - 1;
- } else {
- // If the index is dynamic, decrement it in code.
- at += ' - 1';
- }
- if (mode == 'GET') {
- var code = list + '[' + at + ']';
- return [code, Blockly.JavaScript.ORDER_MEMBER];
- } else if (mode == 'GET_REMOVE') {
- var code = list + '.splice(' + at + ', 1)[0]';
- return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL];
- } else if (mode == 'REMOVE') {
- return list + '.splice(' + at + ', 1);\n';
- }
- } else if (where == 'FROM_END') {
- if (mode == 'GET') {
- var code = list + '.slice(-' + at + ')[0]';
- return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL];
- } else if (mode == 'GET_REMOVE' || mode == 'REMOVE') {
+ switch (where) {
+ case ('FIRST'):
+ if (mode == 'GET') {
+ var code = list + '[0]';
+ return [code, Blockly.JavaScript.ORDER_MEMBER];
+ } else if (mode == 'GET_REMOVE') {
+ var code = list + '.shift()';
+ return [code, Blockly.JavaScript.ORDER_MEMBER];
+ } else if (mode == 'REMOVE') {
+ return list + '.shift();\n';
+ }
+ break;
+ case ('LAST'):
+ if (mode == 'GET') {
+ var code = list + '.slice(-1)[0]';
+ return [code, Blockly.JavaScript.ORDER_MEMBER];
+ } else if (mode == 'GET_REMOVE') {
+ var code = list + '.pop()';
+ return [code, Blockly.JavaScript.ORDER_MEMBER];
+ } else if (mode == 'REMOVE') {
+ return list + '.pop();\n';
+ }
+ break;
+ case ('FROM_START'):
+ var at = Blockly.JavaScript.getAdjusted(block, 'AT');
+ if (mode == 'GET') {
+ var code = list + '[' + at + ']';
+ return [code, Blockly.JavaScript.ORDER_MEMBER];
+ } else if (mode == 'GET_REMOVE') {
+ var code = list + '.splice(' + at + ', 1)[0]';
+ return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL];
+ } else if (mode == 'REMOVE') {
+ return list + '.splice(' + at + ', 1);\n';
+ }
+ break;
+ case ('FROM_END'):
+ var at = Blockly.JavaScript.getAdjusted(block, 'AT', 1, true);
+ if (mode == 'GET') {
+ var code = list + '.slice(' + at + ')[0]';
+ return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL];
+ } else if (mode == 'GET_REMOVE') {
+ var code = list + '.splice(' + at + ', 1)[0]';
+ return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL];
+ } else if (mode == 'REMOVE') {
+ return list + '.splice(' + at + ', 1);';
+ }
+ break;
+ case ('RANDOM'):
var functionName = Blockly.JavaScript.provideFunction_(
- 'listsRemoveFromEnd',
- [ 'function ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ +
- '(list, x) {',
- ' x = list.length - x;',
- ' return list.splice(x, 1)[0];',
- '}']);
- code = functionName + '(' + list + ', ' + at + ')';
- if (mode == 'GET_REMOVE') {
+ 'listsGetRandomItem',
+ ['function ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ +
+ '(list, remove) {',
+ ' var x = Math.floor(Math.random() * list.length);',
+ ' if (remove) {',
+ ' return list.splice(x, 1)[0];',
+ ' } else {',
+ ' return list[x];',
+ ' }',
+ '}']);
+ code = functionName + '(' + list + ', ' + (mode != 'GET') + ')';
+ if (mode == 'GET' || mode == 'GET_REMOVE') {
return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL];
} else if (mode == 'REMOVE') {
return code + ';\n';
}
- }
- } else if (where == 'RANDOM') {
- var functionName = Blockly.JavaScript.provideFunction_(
- 'listsGetRandomItem',
- [ 'function ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ +
- '(list, remove) {',
- ' var x = Math.floor(Math.random() * list.length);',
- ' if (remove) {',
- ' return list.splice(x, 1)[0];',
- ' } else {',
- ' return list[x];',
- ' }',
- '}']);
- code = functionName + '(' + list + ', ' + (mode != 'GET') + ')';
- if (mode == 'GET' || mode == 'GET_REMOVE') {
- return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL];
- } else if (mode == 'REMOVE') {
- return code + ';\n';
- }
+ break;
}
throw 'Unhandled combination (lists_getIndex).';
};
@@ -187,8 +180,6 @@ Blockly.JavaScript['lists_setIndex'] = function(block) {
Blockly.JavaScript.ORDER_MEMBER) || '[]';
var mode = block.getFieldValue('MODE') || 'GET';
var where = block.getFieldValue('WHERE') || 'FROM_START';
- var at = Blockly.JavaScript.valueToCode(block, 'AT',
- Blockly.JavaScript.ORDER_NONE) || '1';
var value = Blockly.JavaScript.valueToCode(block, 'TO',
Blockly.JavaScript.ORDER_ASSIGNMENT) || 'null';
// Cache non-trivial values to variables to prevent repeated look-ups.
@@ -198,155 +189,206 @@ Blockly.JavaScript['lists_setIndex'] = function(block) {
return '';
}
var listVar = Blockly.JavaScript.variableDB_.getDistinctName(
- 'tmp_list', Blockly.Variables.NAME_TYPE);
+ 'tmpList', Blockly.Variables.NAME_TYPE);
var code = 'var ' + listVar + ' = ' + list + ';\n';
list = listVar;
return code;
}
- if (where == 'FIRST') {
- if (mode == 'SET') {
- return list + '[0] = ' + value + ';\n';
- } else if (mode == 'INSERT') {
- return list + '.unshift(' + value + ');\n';
- }
- } else if (where == 'LAST') {
- if (mode == 'SET') {
+ switch (where) {
+ case ('FIRST'):
+ if (mode == 'SET') {
+ return list + '[0] = ' + value + ';\n';
+ } else if (mode == 'INSERT') {
+ return list + '.unshift(' + value + ');\n';
+ }
+ break;
+ case ('LAST'):
+ if (mode == 'SET') {
+ var code = cacheList();
+ code += list + '[' + list + '.length - 1] = ' + value + ';\n';
+ return code;
+ } else if (mode == 'INSERT') {
+ return list + '.push(' + value + ');\n';
+ }
+ break;
+ case ('FROM_START'):
+ var at = Blockly.JavaScript.getAdjusted(block, 'AT');
+ if (mode == 'SET') {
+ return list + '[' + at + '] = ' + value + ';\n';
+ } else if (mode == 'INSERT') {
+ return list + '.splice(' + at + ', 0, ' + value + ');\n';
+ }
+ break;
+ case ('FROM_END'):
+ var at = Blockly.JavaScript.getAdjusted(block, 'AT', 1, false,
+ Blockly.JavaScript.ORDER_SUBTRACTION);
var code = cacheList();
- code += list + '[' + list + '.length - 1] = ' + value + ';\n';
- return code;
- } else if (mode == 'INSERT') {
- return list + '.push(' + value + ');\n';
- }
- } else if (where == 'FROM_START') {
- // Blockly uses one-based indicies.
- if (Blockly.isNumber(at)) {
- // If the index is a naked number, decrement it right now.
- at = parseFloat(at) - 1;
- } else {
- // If the index is dynamic, decrement it in code.
- at += ' - 1';
- }
- if (mode == 'SET') {
- return list + '[' + at + '] = ' + value + ';\n';
- } else if (mode == 'INSERT') {
- return list + '.splice(' + at + ', 0, ' + value + ');\n';
- }
- } else if (where == 'FROM_END') {
- var code = cacheList();
- if (mode == 'SET') {
- code += list + '[' + list + '.length - ' + at + '] = ' + value + ';\n';
- return code;
- } else if (mode == 'INSERT') {
- code += list + '.splice(' + list + '.length - ' + at + ', 0, ' + value +
- ');\n';
- return code;
- }
- } else if (where == 'RANDOM') {
- var code = cacheList();
- var xVar = Blockly.JavaScript.variableDB_.getDistinctName(
- 'tmp_x', Blockly.Variables.NAME_TYPE);
- code += 'var ' + xVar + ' = Math.floor(Math.random() * ' + list +
- '.length);\n';
- if (mode == 'SET') {
- code += list + '[' + xVar + '] = ' + value + ';\n';
- return code;
- } else if (mode == 'INSERT') {
- code += list + '.splice(' + xVar + ', 0, ' + value + ');\n';
- return code;
- }
+ if (mode == 'SET') {
+ code += list + '[' + list + '.length - ' + at + '] = ' + value + ';\n';
+ return code;
+ } else if (mode == 'INSERT') {
+ code += list + '.splice(' + list + '.length - ' + at + ', 0, ' + value +
+ ');\n';
+ return code;
+ }
+ break;
+ case ('RANDOM'):
+ var code = cacheList();
+ var xVar = Blockly.JavaScript.variableDB_.getDistinctName(
+ 'tmpX', Blockly.Variables.NAME_TYPE);
+ code += 'var ' + xVar + ' = Math.floor(Math.random() * ' + list +
+ '.length);\n';
+ if (mode == 'SET') {
+ code += list + '[' + xVar + '] = ' + value + ';\n';
+ return code;
+ } else if (mode == 'INSERT') {
+ code += list + '.splice(' + xVar + ', 0, ' + value + ');\n';
+ return code;
+ }
+ break;
}
throw 'Unhandled combination (lists_setIndex).';
};
+/**
+ * Returns an expression calculating the index into a list.
+ * @private
+ * @param {string} listName Name of the list, used to calculate length.
+ * @param {string} where The method of indexing, selected by dropdown in Blockly
+ * @param {string=} opt_at The optional offset when indexing from start/end.
+ * @return {string} Index expression.
+ */
+Blockly.JavaScript.lists.getIndex_ = function(listName, where, opt_at) {
+ if (where == 'FIRST') {
+ return '0';
+ } else if (where == 'FROM_END') {
+ return listName + '.length - 1 - ' + opt_at;
+ } else if (where == 'LAST') {
+ return listName + '.length - 1';
+ } else {
+ return opt_at;
+ }
+};
+
Blockly.JavaScript['lists_getSublist'] = function(block) {
// Get sublist.
var list = Blockly.JavaScript.valueToCode(block, 'LIST',
Blockly.JavaScript.ORDER_MEMBER) || '[]';
var where1 = block.getFieldValue('WHERE1');
var where2 = block.getFieldValue('WHERE2');
- var at1 = Blockly.JavaScript.valueToCode(block, 'AT1',
- Blockly.JavaScript.ORDER_NONE) || '1';
- var at2 = Blockly.JavaScript.valueToCode(block, 'AT2',
- Blockly.JavaScript.ORDER_NONE) || '1';
if (where1 == 'FIRST' && where2 == 'LAST') {
- var code = list + '.concat()';
+ var code = list + '.slice(0)';
+ } else if (list.match(/^\w+$/) ||
+ (where1 != 'FROM_END' && where2 == 'FROM_START')) {
+ // If the list is a variable or doesn't require a call for length, don't
+ // generate a helper function.
+ switch (where1) {
+ case 'FROM_START':
+ var at1 = Blockly.JavaScript.getAdjusted(block, 'AT1');
+ break;
+ case 'FROM_END':
+ var at1 = Blockly.JavaScript.getAdjusted(block, 'AT1', 1, false,
+ Blockly.JavaScript.ORDER_SUBTRACTION);
+ at1 = list + '.length - ' + at1;
+ break;
+ case 'FIRST':
+ var at1 = '0';
+ break;
+ default:
+ throw 'Unhandled option (lists_getSublist).';
+ }
+ switch (where2) {
+ case 'FROM_START':
+ var at2 = Blockly.JavaScript.getAdjusted(block, 'AT2', 1);
+ break;
+ case 'FROM_END':
+ var at2 = Blockly.JavaScript.getAdjusted(block, 'AT2', 0, false,
+ Blockly.JavaScript.ORDER_SUBTRACTION);
+ at2 = list + '.length - ' + at2;
+ break;
+ case 'LAST':
+ var at2 = list + '.length';
+ break;
+ default:
+ throw 'Unhandled option (lists_getSublist).';
+ }
+ code = list + '.slice(' + at1 + ', ' + at2 + ')';
} else {
+ var at1 = Blockly.JavaScript.getAdjusted(block, 'AT1');
+ var at2 = Blockly.JavaScript.getAdjusted(block, 'AT2');
+ var getIndex_ = Blockly.JavaScript.lists.getIndex_;
+ var wherePascalCase = {'FIRST': 'First', 'LAST': 'Last',
+ 'FROM_START': 'FromStart', 'FROM_END': 'FromEnd'};
var functionName = Blockly.JavaScript.provideFunction_(
- 'listsGetSublist',
- [ 'function ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ +
- '(list, where1, at1, where2, at2) {',
- ' function getAt(where, at) {',
- ' if (where == \'FROM_START\') {',
- ' at--;',
- ' } else if (where == \'FROM_END\') {',
- ' at = list.length - at;',
- ' } else if (where == \'FIRST\') {',
- ' at = 0;',
- ' } else if (where == \'LAST\') {',
- ' at = list.length - 1;',
- ' } else {',
- ' throw \'Unhandled option (lists_getSublist).\';',
- ' }',
- ' return at;',
- ' }',
- ' at1 = getAt(where1, at1);',
- ' at2 = getAt(where2, at2) + 1;',
- ' return list.slice(at1, at2);',
+ 'subsequence' + wherePascalCase[where1] + wherePascalCase[where2],
+ ['function ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ +
+ '(sequence' +
+ // The value for 'FROM_END' and'FROM_START' depends on `at` so
+ // we add it as a parameter.
+ ((where1 == 'FROM_END' || where1 == 'FROM_START') ? ', at1' : '') +
+ ((where2 == 'FROM_END' || where2 == 'FROM_START') ? ', at2' : '') +
+ ') {',
+ ' var start = ' + getIndex_('sequence', where1, 'at1') + ';',
+ ' var end = ' + getIndex_('sequence', where2, 'at2') + ' + 1;',
+ ' return sequence.slice(start, end);',
'}']);
- var code = functionName + '(' + list + ', \'' +
- where1 + '\', ' + at1 + ', \'' + where2 + '\', ' + at2 + ')';
+ var code = functionName + '(' + list +
+ // The value for 'FROM_END' and 'FROM_START' depends on `at` so we
+ // pass it.
+ ((where1 == 'FROM_END' || where1 == 'FROM_START') ? ', ' + at1 : '') +
+ ((where2 == 'FROM_END' || where2 == 'FROM_START') ? ', ' + at2 : '') +
+ ')';
}
return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL];
};
Blockly.JavaScript['lists_sort'] = function(block) {
// Block for sorting a list.
- var listCode = Blockly.JavaScript.valueToCode(
- block, 'LIST',
+ var list = Blockly.JavaScript.valueToCode(block, 'LIST',
Blockly.JavaScript.ORDER_FUNCTION_CALL) || '[]';
var direction = block.getFieldValue('DIRECTION') === '1' ? 1 : -1;
var type = block.getFieldValue('TYPE');
var getCompareFunctionName = Blockly.JavaScript.provideFunction_(
- 'listsGetSortCompare',
- ['function ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ +
- '(type, direction) {',
- ' var compareFuncs = {',
- ' "NUMERIC": function(a, b) {',
- ' return parseFloat(a) - parseFloat(b); },',
- ' "TEXT": function(a, b) {',
- ' return a.toString() > b.toString() ? 1 : -1; },',
- ' "IGNORE_CASE": function(a, b) {',
- ' return a.toString().toLowerCase() > ' +
- 'b.toString().toLowerCase() ? 1 : -1; },',
- ' };',
- ' var compare = compareFuncs[type];',
- ' return function(a, b) { return compare(a, b) * direction; }',
- '}']);
- return ['(' + listCode + ').slice().sort(' +
+ 'listsGetSortCompare',
+ ['function ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ +
+ '(type, direction) {',
+ ' var compareFuncs = {',
+ ' "NUMERIC": function(a, b) {',
+ ' return parseFloat(a) - parseFloat(b); },',
+ ' "TEXT": function(a, b) {',
+ ' return a.toString() > b.toString() ? 1 : -1; },',
+ ' "IGNORE_CASE": function(a, b) {',
+ ' return a.toString().toLowerCase() > ' +
+ 'b.toString().toLowerCase() ? 1 : -1; },',
+ ' };',
+ ' var compare = compareFuncs[type];',
+ ' return function(a, b) { return compare(a, b) * direction; }',
+ '}']);
+ return [list + '.slice().sort(' +
getCompareFunctionName + '("' + type + '", ' + direction + '))',
Blockly.JavaScript.ORDER_FUNCTION_CALL];
};
Blockly.JavaScript['lists_split'] = function(block) {
// Block for splitting text into a list, or joining a list into text.
- var value_input = Blockly.JavaScript.valueToCode(block, 'INPUT',
+ var input = Blockly.JavaScript.valueToCode(block, 'INPUT',
Blockly.JavaScript.ORDER_MEMBER);
- var value_delim = Blockly.JavaScript.valueToCode(block, 'DELIM',
+ var delimiter = Blockly.JavaScript.valueToCode(block, 'DELIM',
Blockly.JavaScript.ORDER_NONE) || '\'\'';
var mode = block.getFieldValue('MODE');
if (mode == 'SPLIT') {
- if (!value_input) {
- value_input = '\'\'';
+ if (!input) {
+ input = '\'\'';
}
var functionName = 'split';
} else if (mode == 'JOIN') {
- if (!value_input) {
- value_input = '[]';
+ if (!input) {
+ input = '[]';
}
var functionName = 'join';
} else {
throw 'Unknown mode: ' + mode;
}
- var code = value_input + '.' + functionName + '(' + value_delim + ')';
+ var code = input + '.' + functionName + '(' + delimiter + ')';
return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL];
};
diff --git a/generators/javascript/math.js b/generators/javascript/math.js
index 0a7d14621..a31b94392 100644
--- a/generators/javascript/math.js
+++ b/generators/javascript/math.js
@@ -168,25 +168,25 @@ Blockly.JavaScript['math_number_property'] = function(block) {
// Prime is a special case as it is not a one-liner test.
var functionName = Blockly.JavaScript.provideFunction_(
'mathIsPrime',
- [ 'function ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ + '(n) {',
- ' // https://en.wikipedia.org/wiki/Primality_test#Naive_methods',
- ' if (n == 2 || n == 3) {',
- ' return true;',
- ' }',
- ' // False if n is NaN, negative, is 1, or not whole.',
- ' // And false if n is divisible by 2 or 3.',
- ' if (isNaN(n) || n <= 1 || n % 1 != 0 || n % 2 == 0 ||' +
+ ['function ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ + '(n) {',
+ ' // https://en.wikipedia.org/wiki/Primality_test#Naive_methods',
+ ' if (n == 2 || n == 3) {',
+ ' return true;',
+ ' }',
+ ' // False if n is NaN, negative, is 1, or not whole.',
+ ' // And false if n is divisible by 2 or 3.',
+ ' if (isNaN(n) || n <= 1 || n % 1 != 0 || n % 2 == 0 ||' +
' n % 3 == 0) {',
- ' return false;',
- ' }',
- ' // Check all the numbers of form 6k +/- 1, up to sqrt(n).',
- ' for (var x = 6; x <= Math.sqrt(n) + 1; x += 6) {',
- ' if (n % (x - 1) == 0 || n % (x + 1) == 0) {',
- ' return false;',
- ' }',
- ' }',
- ' return true;',
- '}']);
+ ' return false;',
+ ' }',
+ ' // Check all the numbers of form 6k +/- 1, up to sqrt(n).',
+ ' for (var x = 6; x <= Math.sqrt(n) + 1; x += 6) {',
+ ' if (n % (x - 1) == 0 || n % (x + 1) == 0) {',
+ ' return false;',
+ ' }',
+ ' }',
+ ' return true;',
+ '}']);
code = functionName + '(' + number_to_check + ')';
return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL];
}
@@ -254,7 +254,7 @@ Blockly.JavaScript['math_on_list'] = function(block) {
// mathMean([null,null,1,3]) == 2.0.
var functionName = Blockly.JavaScript.provideFunction_(
'mathMean',
- [ 'function ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ +
+ ['function ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ +
'(myList) {',
' return myList.reduce(function(x, y) {return x + y;}) / ' +
'myList.length;',
@@ -267,7 +267,7 @@ Blockly.JavaScript['math_on_list'] = function(block) {
// mathMedian([null,null,1,3]) == 2.0.
var functionName = Blockly.JavaScript.provideFunction_(
'mathMedian',
- [ 'function ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ +
+ ['function ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ +
'(myList) {',
' var localList = myList.filter(function (x) ' +
'{return typeof x == \'number\';});',
@@ -290,7 +290,7 @@ Blockly.JavaScript['math_on_list'] = function(block) {
// Mode of [3, 'x', 'x', 1, 1, 2, '3'] -> ['x', 1].
var functionName = Blockly.JavaScript.provideFunction_(
'mathModes',
- [ 'function ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ +
+ ['function ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ +
'(values) {',
' var modes = [];',
' var counts = [];',
@@ -326,7 +326,7 @@ Blockly.JavaScript['math_on_list'] = function(block) {
case 'STD_DEV':
var functionName = Blockly.JavaScript.provideFunction_(
'mathStandardDeviation',
- [ 'function ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ +
+ ['function ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ +
'(numbers) {',
' var n = numbers.length;',
' if (!n) return null;',
@@ -345,7 +345,7 @@ Blockly.JavaScript['math_on_list'] = function(block) {
case 'RANDOM':
var functionName = Blockly.JavaScript.provideFunction_(
'mathRandomList',
- [ 'function ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ +
+ ['function ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ +
'(list) {',
' var x = Math.floor(Math.random() * list.length);',
' return list[x];',
@@ -391,16 +391,16 @@ Blockly.JavaScript['math_random_int'] = function(block) {
Blockly.JavaScript.ORDER_COMMA) || '0';
var functionName = Blockly.JavaScript.provideFunction_(
'mathRandomInt',
- [ 'function ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ +
+ ['function ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ +
'(a, b) {',
- ' if (a > b) {',
- ' // Swap a and b to ensure a is smaller.',
- ' var c = a;',
- ' a = b;',
- ' b = c;',
- ' }',
- ' return Math.floor(Math.random() * (b - a + 1) + a);',
- '}']);
+ ' if (a > b) {',
+ ' // Swap a and b to ensure a is smaller.',
+ ' var c = a;',
+ ' a = b;',
+ ' b = c;',
+ ' }',
+ ' return Math.floor(Math.random() * (b - a + 1) + a);',
+ '}']);
var code = functionName + '(' + argument0 + ', ' + argument1 + ')';
return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL];
};
diff --git a/generators/javascript/text.js b/generators/javascript/text.js
index 86befb9ef..9ecfdc387 100644
--- a/generators/javascript/text.js
+++ b/generators/javascript/text.js
@@ -37,29 +37,29 @@ Blockly.JavaScript['text'] = function(block) {
Blockly.JavaScript['text_join'] = function(block) {
// Create a string made up of any number of elements of any type.
- var code;
- if (block.itemCount_ == 0) {
- return ['\'\'', Blockly.JavaScript.ORDER_ATOMIC];
- } else if (block.itemCount_ == 1) {
- var argument0 = Blockly.JavaScript.valueToCode(block, 'ADD0',
- Blockly.JavaScript.ORDER_NONE) || '\'\'';
- code = 'String(' + argument0 + ')';
- return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL];
- } else if (block.itemCount_ == 2) {
- var argument0 = Blockly.JavaScript.valueToCode(block, 'ADD0',
- Blockly.JavaScript.ORDER_NONE) || '\'\'';
- var argument1 = Blockly.JavaScript.valueToCode(block, 'ADD1',
- Blockly.JavaScript.ORDER_NONE) || '\'\'';
- code = 'String(' + argument0 + ') + String(' + argument1 + ')';
- return [code, Blockly.JavaScript.ORDER_ADDITION];
- } else {
- code = new Array(block.itemCount_);
- for (var n = 0; n < block.itemCount_; n++) {
- code[n] = Blockly.JavaScript.valueToCode(block, 'ADD' + n,
- Blockly.JavaScript.ORDER_COMMA) || '\'\'';
- }
- code = '[' + code.join(',') + '].join(\'\')';
- return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL];
+ switch (block.itemCount_) {
+ case 0:
+ return ['\'\'', Blockly.JavaScript.ORDER_ATOMIC];
+ case 1:
+ var element = Blockly.JavaScript.valueToCode(block, 'ADD0',
+ Blockly.JavaScript.ORDER_NONE) || '\'\'';
+ var code = 'String(' + element + ')';
+ return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL];
+ case 2:
+ var element0 = Blockly.JavaScript.valueToCode(block, 'ADD0',
+ Blockly.JavaScript.ORDER_NONE) || '\'\'';
+ var element1 = Blockly.JavaScript.valueToCode(block, 'ADD1',
+ Blockly.JavaScript.ORDER_NONE) || '\'\'';
+ var code = 'String(' + element0 + ') + String(' + element1 + ')';
+ return [code, Blockly.JavaScript.ORDER_ADDITION];
+ default:
+ var elements = new Array(block.itemCount_);
+ for (var i = 0; i < block.itemCount_; i++) {
+ elements[i] = Blockly.JavaScript.valueToCode(block, 'ADD' + i,
+ Blockly.JavaScript.ORDER_COMMA) || '\'\'';
+ }
+ var code = '[' + elements.join(',') + '].join(\'\')';
+ return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL];
}
};
@@ -67,45 +67,49 @@ Blockly.JavaScript['text_append'] = function(block) {
// Append to a variable in place.
var varName = Blockly.JavaScript.variableDB_.getName(
block.getFieldValue('VAR'), Blockly.Variables.NAME_TYPE);
- var argument0 = Blockly.JavaScript.valueToCode(block, 'TEXT',
+ var value = Blockly.JavaScript.valueToCode(block, 'TEXT',
Blockly.JavaScript.ORDER_NONE) || '\'\'';
- return varName + ' = String(' + varName + ') + String(' + argument0 + ');\n';
+ return varName + ' = String(' + varName + ') + String(' + value + ');\n';
};
Blockly.JavaScript['text_length'] = function(block) {
// String or array length.
- var argument0 = Blockly.JavaScript.valueToCode(block, 'VALUE',
+ var text = Blockly.JavaScript.valueToCode(block, 'VALUE',
Blockly.JavaScript.ORDER_FUNCTION_CALL) || '\'\'';
- return [argument0 + '.length', Blockly.JavaScript.ORDER_MEMBER];
+ return [text + '.length', Blockly.JavaScript.ORDER_MEMBER];
};
Blockly.JavaScript['text_isEmpty'] = function(block) {
// Is the string null or array empty?
- var argument0 = Blockly.JavaScript.valueToCode(block, 'VALUE',
+ var text = Blockly.JavaScript.valueToCode(block, 'VALUE',
Blockly.JavaScript.ORDER_MEMBER) || '\'\'';
- return ['!' + argument0 + '.length', Blockly.JavaScript.ORDER_LOGICAL_NOT];
+ return ['!' + text + '.length', Blockly.JavaScript.ORDER_LOGICAL_NOT];
};
Blockly.JavaScript['text_indexOf'] = function(block) {
// Search the text for a substring.
var operator = block.getFieldValue('END') == 'FIRST' ?
'indexOf' : 'lastIndexOf';
- var argument0 = Blockly.JavaScript.valueToCode(block, 'FIND',
+ var substring = Blockly.JavaScript.valueToCode(block, 'FIND',
Blockly.JavaScript.ORDER_NONE) || '\'\'';
- var argument1 = Blockly.JavaScript.valueToCode(block, 'VALUE',
+ var text = Blockly.JavaScript.valueToCode(block, 'VALUE',
Blockly.JavaScript.ORDER_MEMBER) || '\'\'';
- var code = argument1 + '.' + operator + '(' + argument0 + ') + 1';
- return [code, Blockly.JavaScript.ORDER_ADDITION];
+ var code = text + '.' + operator + '(' + substring + ')';
+ // Adjust index if using one-based indices.
+ if (Blockly.JavaScript.ONE_BASED_INDEXING) {
+ return [code + ' + 1', Blockly.JavaScript.ORDER_ADDITION];
+ }
+ return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL];
};
Blockly.JavaScript['text_charAt'] = function(block) {
// Get letter at index.
// Note: Until January 2013 this block did not have the WHERE input.
var where = block.getFieldValue('WHERE') || 'FROM_START';
- var at = Blockly.JavaScript.valueToCode(block, 'AT',
- Blockly.JavaScript.ORDER_UNARY_NEGATION) || '1';
+ var textOrder = (where == 'RANDOM') ? Blockly.JavaScript.ORDER_NONE :
+ Blockly.JavaScript.ORDER_MEMBER;
var text = Blockly.JavaScript.valueToCode(block, 'VALUE',
- Blockly.JavaScript.ORDER_MEMBER) || '\'\'';
+ textOrder) || '\'\'';
switch (where) {
case 'FIRST':
var code = text + '.charAt(0)';
@@ -114,70 +118,117 @@ Blockly.JavaScript['text_charAt'] = function(block) {
var code = text + '.slice(-1)';
return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL];
case 'FROM_START':
- // Blockly uses one-based indicies.
- if (Blockly.isNumber(at)) {
- // If the index is a naked number, decrement it right now.
- at = parseFloat(at) - 1;
- } else {
- // If the index is dynamic, decrement it in code.
- at += ' - 1';
- }
+ var at = Blockly.JavaScript.getAdjusted(block, 'AT');
+ // Adjust index if using one-based indices.
var code = text + '.charAt(' + at + ')';
return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL];
case 'FROM_END':
- var code = text + '.slice(-' + at + ').charAt(0)';
+ var at = Blockly.JavaScript.getAdjusted(block, 'AT', 1, true);
+ var code = text + '.slice(' + at + ').charAt(0)';
return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL];
case 'RANDOM':
var functionName = Blockly.JavaScript.provideFunction_(
'textRandomLetter',
- [ 'function ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ +
+ ['function ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ +
'(text) {',
- ' var x = Math.floor(Math.random() * text.length);',
- ' return text[x];',
- '}']);
- code = functionName + '(' + text + ')';
+ ' var x = Math.floor(Math.random() * text.length);',
+ ' return text[x];',
+ '}']);
+ var code = functionName + '(' + text + ')';
return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL];
}
throw 'Unhandled option (text_charAt).';
};
+/**
+ * Returns an expression calculating the index into a string.
+ * @private
+ * @param {string} stringName Name of the string, used to calculate length.
+ * @param {string} where The method of indexing, selected by dropdown in Blockly
+ * @param {string=} opt_at The optional offset when indexing from start/end.
+ * @return {string} Index expression.
+ */
+Blockly.JavaScript.text.getIndex_ = function(stringName, where, opt_at) {
+ if (where == 'FIRST') {
+ return '0';
+ } else if (where == 'FROM_END') {
+ return stringName + '.length - 1 - ' + opt_at;
+ } else if (where == 'LAST') {
+ return stringName + '.length - 1';
+ } else {
+ return opt_at;
+ }
+};
+
Blockly.JavaScript['text_getSubstring'] = function(block) {
// Get substring.
var text = Blockly.JavaScript.valueToCode(block, 'STRING',
- Blockly.JavaScript.ORDER_MEMBER) || '\'\'';
+ Blockly.JavaScript.ORDER_FUNCTION_CALL) || '\'\'';
var where1 = block.getFieldValue('WHERE1');
var where2 = block.getFieldValue('WHERE2');
- var at1 = Blockly.JavaScript.valueToCode(block, 'AT1',
- Blockly.JavaScript.ORDER_NONE) || '1';
- var at2 = Blockly.JavaScript.valueToCode(block, 'AT2',
- Blockly.JavaScript.ORDER_NONE) || '1';
if (where1 == 'FIRST' && where2 == 'LAST') {
var code = text;
+ } else if (text.match(/^'?\w+'?$/) ||
+ (where1 != 'FROM_END' && where1 != 'LAST' &&
+ where2 != 'FROM_END' && where2 != 'LAST')) {
+ // If the text is a variable or literal or doesn't require a call for
+ // length, don't generate a helper function.
+ switch (where1) {
+ case 'FROM_START':
+ var at1 = Blockly.JavaScript.getAdjusted(block, 'AT1');
+ break;
+ case 'FROM_END':
+ var at1 = Blockly.JavaScript.getAdjusted(block, 'AT1', 1, false,
+ Blockly.JavaScript.ORDER_SUBTRACTION);
+ at1 = text + '.length - ' + at1;
+ break;
+ case 'FIRST':
+ var at1 = '0';
+ break;
+ default:
+ throw 'Unhandled option (text_getSubstring).';
+ }
+ switch (where2) {
+ case 'FROM_START':
+ var at2 = Blockly.JavaScript.getAdjusted(block, 'AT2', 1);
+ break;
+ case 'FROM_END':
+ var at2 = Blockly.JavaScript.getAdjusted(block, 'AT2', 0, false,
+ Blockly.JavaScript.ORDER_SUBTRACTION);
+ at2 = text + '.length - ' + at2;
+ break;
+ case 'LAST':
+ var at2 = text + '.length';
+ break;
+ default:
+ throw 'Unhandled option (text_getSubstring).';
+ }
+ code = text + '.slice(' + at1 + ', ' + at2 + ')';
} else {
+ var at1 = Blockly.JavaScript.getAdjusted(block, 'AT1');
+ var at2 = Blockly.JavaScript.getAdjusted(block, 'AT2');
+ var getIndex_ = Blockly.JavaScript.text.getIndex_;
+ var wherePascalCase = {'FIRST': 'First', 'LAST': 'Last',
+ 'FROM_START': 'FromStart', 'FROM_END': 'FromEnd'};
var functionName = Blockly.JavaScript.provideFunction_(
- 'textGetSubstring',
- [ 'function ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ +
- '(text, where1, at1, where2, at2) {',
- ' function getAt(where, at) {',
- ' if (where == \'FROM_START\') {',
- ' at--;',
- ' } else if (where == \'FROM_END\') {',
- ' at = text.length - at;',
- ' } else if (where == \'FIRST\') {',
- ' at = 0;',
- ' } else if (where == \'LAST\') {',
- ' at = text.length - 1;',
- ' } else {',
- ' throw \'Unhandled option (text_getSubstring).\';',
- ' }',
- ' return at;',
- ' }',
- ' at1 = getAt(where1, at1);',
- ' at2 = getAt(where2, at2) + 1;',
- ' return text.slice(at1, at2);',
+ 'subsequence' + wherePascalCase[where1] + wherePascalCase[where2],
+ ['function ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ +
+ '(sequence' +
+ // The value for 'FROM_END' and'FROM_START' depends on `at` so
+ // we add it as a parameter.
+ ((where1 == 'FROM_END' || where1 == 'FROM_START') ? ', at1' : '') +
+ ((where2 == 'FROM_END' || where2 == 'FROM_START') ? ', at2' : '') +
+ ') {',
+ ' var start = ' + getIndex_('sequence', where1, 'at1') + ';',
+ ' var end = ' + getIndex_('sequence', where2, 'at2') + ' + 1;',
+ ' return sequence.slice(start, end);',
'}']);
- var code = functionName + '(' + text + ', \'' +
- where1 + '\', ' + at1 + ', \'' + where2 + '\', ' + at2 + ')';
+ var code = functionName + '(' + text +
+ // The value for 'FROM_END' and 'FROM_START' depends on `at` so we
+ // pass it.
+ ((where1 == 'FROM_END' || where1 == 'FROM_START') ? ', ' + at1 : '') +
+ ((where2 == 'FROM_END' || where2 == 'FROM_START') ? ', ' + at2 : '') +
+ ')';
}
return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL];
};
@@ -190,25 +241,24 @@ Blockly.JavaScript['text_changeCase'] = function(block) {
'TITLECASE': null
};
var operator = OPERATORS[block.getFieldValue('CASE')];
- var code;
+ var textOrder = operator ? Blockly.JavaScript.ORDER_MEMBER :
+ Blockly.JavaScript.ORDER_NONE;
+ var text = Blockly.JavaScript.valueToCode(block, 'TEXT',
+ textOrder) || '\'\'';
if (operator) {
// Upper and lower case are functions built into JavaScript.
- var argument0 = Blockly.JavaScript.valueToCode(block, 'TEXT',
- Blockly.JavaScript.ORDER_MEMBER) || '\'\'';
- code = argument0 + operator;
+ var code = text + operator;
} else {
// Title case is not a native JavaScript function. Define one.
var functionName = Blockly.JavaScript.provideFunction_(
'textToTitleCase',
- [ 'function ' +
- Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ + '(str) {',
- ' return str.replace(/\\S+/g,',
- ' function(txt) {return txt[0].toUpperCase() + ' +
- 'txt.substring(1).toLowerCase();});',
- '}']);
- var argument0 = Blockly.JavaScript.valueToCode(block, 'TEXT',
- Blockly.JavaScript.ORDER_NONE) || '\'\'';
- code = functionName + '(' + argument0 + ')';
+ ['function ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ +
+ '(str) {',
+ ' return str.replace(/\\S+/g,',
+ ' function(txt) {return txt[0].toUpperCase() + ' +
+ 'txt.substring(1).toLowerCase();});',
+ '}']);
+ var code = functionName + '(' + text + ')';
}
return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL];
};
@@ -221,16 +271,16 @@ Blockly.JavaScript['text_trim'] = function(block) {
'BOTH': '.trim()'
};
var operator = OPERATORS[block.getFieldValue('MODE')];
- var argument0 = Blockly.JavaScript.valueToCode(block, 'TEXT',
+ var text = Blockly.JavaScript.valueToCode(block, 'TEXT',
Blockly.JavaScript.ORDER_MEMBER) || '\'\'';
- return [argument0 + operator, Blockly.JavaScript.ORDER_FUNCTION_CALL];
+ return [text + operator, Blockly.JavaScript.ORDER_FUNCTION_CALL];
};
Blockly.JavaScript['text_print'] = function(block) {
// Print statement.
- var argument0 = Blockly.JavaScript.valueToCode(block, 'TEXT',
+ var msg = Blockly.JavaScript.valueToCode(block, 'TEXT',
Blockly.JavaScript.ORDER_NONE) || '\'\'';
- return 'window.alert(' + argument0 + ');\n';
+ return 'window.alert(' + msg + ');\n';
};
Blockly.JavaScript['text_prompt_ext'] = function(block) {
diff --git a/generators/lua.js b/generators/lua.js
index 60a6c0e14..3f7df6b1c 100644
--- a/generators/lua.js
+++ b/generators/lua.js
@@ -77,7 +77,7 @@ Blockly.Lua.ORDER_ATOMIC = 0; // literals
// The next level was not explicit in documentation and inferred by Ellen.
Blockly.Lua.ORDER_HIGH = 1; // Function calls, tables[]
Blockly.Lua.ORDER_EXPONENTIATION = 2; // ^
-Blockly.Lua.ORDER_UNARY = 3; // not # - ()
+Blockly.Lua.ORDER_UNARY = 3; // not # - ~
Blockly.Lua.ORDER_MULTIPLICATIVE = 4; // * / %
Blockly.Lua.ORDER_ADDITIVE = 5; // + -
Blockly.Lua.ORDER_CONCATENATION = 6; // ..
@@ -86,6 +86,12 @@ Blockly.Lua.ORDER_AND = 8; // and
Blockly.Lua.ORDER_OR = 9; // or
Blockly.Lua.ORDER_NONE = 99;
+/**
+ * Lua is not supporting zero-indexing since the language itself is one-indexed,
+ * so there is not flag for ONE_BASED_INDEXING to indicate which indexing is
+ * used for lists and text.
+ */
+
/**
* Initialise the database of variable names.
* @param {!Blockly.Workspace} workspace Workspace to generate code from.
@@ -170,9 +176,9 @@ Blockly.Lua.scrub_ = function(block, code) {
}
// Collect comments for all value arguments.
// Don't collect comments for nested statements.
- for (var x = 0; x < block.inputList.length; x++) {
- if (block.inputList[x].type == Blockly.INPUT_VALUE) {
- var childBlock = block.inputList[x].connection.targetBlock();
+ for (var i = 0; i < block.inputList.length; i++) {
+ if (block.inputList[i].type == Blockly.INPUT_VALUE) {
+ var childBlock = block.inputList[i].connection.targetBlock();
if (childBlock) {
comment = Blockly.Lua.allNestedComments(childBlock);
if (comment) {
diff --git a/generators/lua/lists.js b/generators/lua/lists.js
index 8c89a1bd3..5b7711dbb 100644
--- a/generators/lua/lists.js
+++ b/generators/lua/lists.js
@@ -31,18 +31,17 @@ goog.require('Blockly.Lua');
Blockly.Lua['lists_create_empty'] = function(block) {
// Create an empty list.
- // List literals must be parenthesized before indexing into.
- return ['({})', Blockly.Lua.ORDER_ATOMIC];
+ return ['{}', Blockly.Lua.ORDER_ATOMIC];
};
Blockly.Lua['lists_create_with'] = function(block) {
// Create a list with any number of elements of any type.
- var code = new Array(block.itemCount_);
- for (var n = 0; n < block.itemCount_; n++) {
- code[n] = Blockly.Lua.valueToCode(block, 'ADD' + n,
+ var elements = new Array(block.itemCount_);
+ for (var i = 0; i < block.itemCount_; i++) {
+ elements[i] = Blockly.Lua.valueToCode(block, 'ADD' + i,
Blockly.Lua.ORDER_NONE) || 'None';
}
- code = '({' + code.join(', ') + '})';
+ var code = '{' + elements.join(', ') + '}';
return [code, Blockly.Lua.ORDER_ATOMIC];
};
@@ -57,38 +56,37 @@ Blockly.Lua['lists_repeat'] = function(block) {
' end',
' return t',
'end']);
- var argument0 = Blockly.Lua.valueToCode(block, 'ITEM',
+ var element = Blockly.Lua.valueToCode(block, 'ITEM',
Blockly.Lua.ORDER_NONE) || 'None';
- var argument1 = Blockly.Lua.valueToCode(block, 'NUM',
+ var repeatCount = Blockly.Lua.valueToCode(block, 'NUM',
Blockly.Lua.ORDER_NONE) || '0';
- var code = functionName + '(' + argument0 + ', ' + argument1 + ')';
+ var code = functionName + '(' + element + ', ' + repeatCount + ')';
return [code, Blockly.Lua.ORDER_HIGH];
};
Blockly.Lua['lists_length'] = function(block) {
// String or array length.
- var argument0 = Blockly.Lua.valueToCode(block, 'VALUE',
- Blockly.Lua.ORDER_HIGH) || '({})';
- return ['#' + argument0, Blockly.Lua.ORDER_HIGH];
+ var list = Blockly.Lua.valueToCode(block, 'VALUE',
+ Blockly.Lua.ORDER_UNARY) || '{}';
+ return ['#' + list, Blockly.Lua.ORDER_UNARY];
};
Blockly.Lua['lists_isEmpty'] = function(block) {
// Is the string null or array empty?
- var argument0 = Blockly.Lua.valueToCode(block, 'VALUE',
- Blockly.Lua.ORDER_HIGH) || '({})';
- var code = '#' + argument0 + ' == 0';
+ var list = Blockly.Lua.valueToCode(block, 'VALUE',
+ Blockly.Lua.ORDER_UNARY) || '{}';
+ var code = '#' + list + ' == 0';
return [code, Blockly.Lua.ORDER_RELATIONAL];
};
Blockly.Lua['lists_indexOf'] = function(block) {
// Find an item in the list.
- var argument0 = Blockly.Lua.valueToCode(block, 'FIND',
+ var item = Blockly.Lua.valueToCode(block, 'FIND',
Blockly.Lua.ORDER_NONE) || '\'\'';
- var argument1 = Blockly.Lua.valueToCode(block, 'VALUE',
- Blockly.Lua.ORDER_NONE) || '({})';
- var functionName;
+ var list = Blockly.Lua.valueToCode(block, 'VALUE',
+ Blockly.Lua.ORDER_NONE) || '{}';
if (block.getFieldValue('END') == 'FIRST') {
- functionName = Blockly.Lua.provideFunction_(
+ var functionName = Blockly.Lua.provideFunction_(
'first_index',
['function ' + Blockly.Lua.FUNCTION_NAME_PLACEHOLDER_ + '(t, elem)',
' for k, v in ipairs(t) do',
@@ -99,7 +97,7 @@ Blockly.Lua['lists_indexOf'] = function(block) {
' return 0',
'end']);
} else {
- functionName = Blockly.Lua.provideFunction_(
+ var functionName = Blockly.Lua.provideFunction_(
'last_index',
['function ' + Blockly.Lua.FUNCTION_NAME_PLACEHOLDER_ + '(t, elem)',
' for i = #t, 1, -1 do',
@@ -110,64 +108,40 @@ Blockly.Lua['lists_indexOf'] = function(block) {
' return 0',
'end']);
}
- var code = functionName + '(' + argument1 + ', ' + argument0 + ')';
+ var code = functionName + '(' + list + ', ' + item + ')';
return [code, Blockly.Lua.ORDER_HIGH];
};
/**
* Returns an expression calculating the index into a list.
* @private
- * @param {string} listname Name of the list, used to calculate length.
+ * @param {string} listName Name of the list, used to calculate length.
* @param {string} where The method of indexing, selected by dropdown in Blockly
* @param {string=} opt_at The optional offset when indexing from start/end.
* @return {string} Index expression.
*/
-Blockly.Lua.lists.getIndex_ = function(listname, where, opt_at) {
+Blockly.Lua.lists.getIndex_ = function(listName, where, opt_at) {
if (where == 'FIRST') {
return '1';
} else if (where == 'FROM_END') {
- return '#' + listname + ' + 1 - ' + opt_at;
+ return '#' + listName + ' + 1 - ' + opt_at;
} else if (where == 'LAST') {
- return '#' + listname;
+ return '#' + listName;
} else if (where == 'RANDOM') {
- return 'math.random(#' + listname + ')';
+ return 'math.random(#' + listName + ')';
} else {
return opt_at;
}
};
-/**
- * Counter for generating unique symbols.
- * @private
- * @type {number}
- */
-Blockly.Lua.lists.gensym_counter_ = 0;
-
-/**
- * Generate a unique symbol.
- * @private
- * @return {string} unique symbol, eg 'G123'
- */
-Blockly.Lua.lists.gensym_ = function() {
- return 'G' + Blockly.Lua.lists.gensym_counter_++;
-};
-
Blockly.Lua['lists_getIndex'] = function(block) {
// Get element at index.
// Note: Until January 2013 this block did not have MODE or WHERE inputs.
var mode = block.getFieldValue('MODE') || 'GET';
var where = block.getFieldValue('WHERE') || 'FROM_START';
- var at = Blockly.Lua.valueToCode(block, 'AT',
- Blockly.Lua.ORDER_ADDITIVE) || '1';
- if (mode == 'GET') {
- var order = Blockly.Lua.ORDER_HIGH;
- } else {
- // List will be an argument in a function call.
- var order = Blockly.Lua.ORDER_NONE;
- }
- var list = Blockly.Lua.valueToCode(block, 'VALUE', order) || '({})';
+ var list = Blockly.Lua.valueToCode(block, 'VALUE', Blockly.Lua.ORDER_HIGH) ||
+ '{}';
var getIndex_ = Blockly.Lua.lists.getIndex_;
- var gensym_ = Blockly.Lua.lists.gensym_;
// If `list` would be evaluated more than once (which is the case for LAST,
// FROM_END, and RANDOM) and is non-trivial, make sure to access it only once.
@@ -176,46 +150,59 @@ Blockly.Lua['lists_getIndex'] = function(block) {
// `list` is an expression, so we may not evaluate it more than once.
if (mode == 'REMOVE') {
// We can use multiple statements.
+ var atOrder = (where == 'FROM_END') ? Blockly.Lua.ORDER_ADDITIVE :
+ Blockly.Lua.ORDER_NONE;
+ var at = Blockly.Lua.valueToCode(block, 'AT', atOrder) || '1';
var listVar = Blockly.Lua.variableDB_.getDistinctName(
'tmp_list', Blockly.Variables.NAME_TYPE);
+ at = getIndex_(listVar, where, at);
var code = listVar + ' = ' + list + '\n' +
- 'table.remove(' + listVar + ', ' + getIndex_(listVar, where, at) +
- ')\n';
+ 'table.remove(' + listVar + ', ' + at + ')\n';
return code;
} else {
// We need to create a procedure to avoid reevaluating values.
+ var at = Blockly.Lua.valueToCode(block, 'AT', Blockly.Lua.ORDER_NONE) ||
+ '1';
if (mode == 'GET') {
- // Note that getIndex_() ignores `at` when `where` == 'LAST' or
- // 'RANDOM', so we only need one procedure for each of those 'where'
- // values. The value for 'FROM_END' depends on `at`, so we will
- // generate a unique procedure (name) each time.
var functionName = Blockly.Lua.provideFunction_(
- 'list_get_' + where.toLowerCase() +
- (where == 'FROM_END' ? '_' + gensym_() : ''),
- ['function ' + Blockly.Lua.FUNCTION_NAME_PLACEHOLDER_ + '(t)',
- ' return t[' + getIndex_('t', where, at) + ']',
+ 'list_get_' + where.toLowerCase(),
+ ['function ' + Blockly.Lua.FUNCTION_NAME_PLACEHOLDER_ + '(t' +
+ // The value for 'FROM_END' and'FROM_START' depends on `at` so
+ // we add it as a parameter.
+ ((where == 'FROM_END' || where == 'FROM_START') ?
+ ', at)' : ')'),
+ ' return t[' + getIndex_('t', where, 'at') + ']',
'end']);
- } else { // mode == 'GET_REMOVE'
- // We need to create a procedure.
+ } else { // mode == 'GET_REMOVE'
var functionName = Blockly.Lua.provideFunction_(
- 'list_remove_' + where.toLowerCase() +
- (where == 'FROM_END' ? '_' + gensym_() : ''),
- ['function ' + Blockly.Lua.FUNCTION_NAME_PLACEHOLDER_ + '(t)',
- ' return table.remove(t, ' + getIndex_('t', where, at) + ')',
+ 'list_remove_' + where.toLowerCase(),
+ ['function ' + Blockly.Lua.FUNCTION_NAME_PLACEHOLDER_ + '(t' +
+ // The value for 'FROM_END' and'FROM_START' depends on `at` so
+ // we add it as a parameter.
+ ((where == 'FROM_END' || where == 'FROM_START') ?
+ ', at)' : ')'),
+ ' return table.remove(t, ' + getIndex_('t', where, 'at') + ')',
'end']);
}
- var code = functionName + '(' + list + ')';
+ var code = functionName + '(' + list +
+ // The value for 'FROM_END' and 'FROM_START' depends on `at` so we
+ // pass it.
+ ((where == 'FROM_END' || where == 'FROM_START') ? ', ' + at : '') +
+ ')';
return [code, Blockly.Lua.ORDER_HIGH];
}
} else {
// Either `list` is a simple variable, or we only need to refer to `list`
// once.
+ var atOrder = (mode == 'GET' && where == 'FROM_END') ?
+ Blockly.Lua.ORDER_ADDITIVE : Blockly.Lua.ORDER_NONE;
+ var at = Blockly.Lua.valueToCode(block, 'AT', atOrder) || '1';
+ at = getIndex_(list, where, at);
if (mode == 'GET') {
- var code = list + '[' + getIndex_(list, where, at) + ']';
+ var code = list + '[' + at + ']';
return [code, Blockly.Lua.ORDER_HIGH];
} else {
- var code = 'table.remove(' + list + ', ' + getIndex_(list, where, at) +
- ')';
+ var code = 'table.remove(' + list + ', ' + at + ')';
if (mode == 'GET_REMOVE') {
return [code, Blockly.Lua.ORDER_HIGH];
} else { // `mode` == 'REMOVE'
@@ -229,7 +216,7 @@ Blockly.Lua['lists_setIndex'] = function(block) {
// Set element at index.
// Note: Until February 2013 this block did not have MODE or WHERE inputs.
var list = Blockly.Lua.valueToCode(block, 'LIST',
- Blockly.Lua.ORDER_HIGH) || '({})';
+ Blockly.Lua.ORDER_HIGH) || '{}';
var mode = block.getFieldValue('MODE') || 'SET';
var where = block.getFieldValue('WHERE') || 'FROM_START';
var at = Blockly.Lua.valueToCode(block, 'AT',
@@ -238,97 +225,71 @@ Blockly.Lua['lists_setIndex'] = function(block) {
Blockly.Lua.ORDER_NONE) || 'None';
var getIndex_ = Blockly.Lua.lists.getIndex_;
+ var code = '';
// If `list` would be evaluated more than once (which is the case for LAST,
// FROM_END, and RANDOM) and is non-trivial, make sure to access it only once.
if ((where == 'LAST' || where == 'FROM_END' || where == 'RANDOM') &&
!list.match(/^\w+$/)) {
// `list` is an expression, so we may not evaluate it more than once.
- if (where == 'RANDOM' || where == 'LAST') {
- // In these cases, `at` is implicit. getIndex_() ignores its value.
- if (mode == 'SET') {
- var functionName = Blockly.Lua.provideFunction_(
- 'list_set_' + where.toLowerCase(),
- ['function ' + Blockly.Lua.FUNCTION_NAME_PLACEHOLDER_ + '(t, val)',
- ' t[' + getIndex_('t', where, at) + '] = val',
- 'end']);
- } else { // `mode` == 'INSERT'
- var functionName = Blockly.Lua.provideFunction_(
- 'list_insert_' + where.toLowerCase(),
- ['function ' + Blockly.Lua.FUNCTION_NAME_PLACEHOLDER_ + '(t, val)',
- ' table.insert(t, ' +
- // LAST is a special case, because we want to insert
- // *after* not *before*, the existing last element.
- getIndex_('t', where, at) + (where == 'LAST' ? ' + 1' : '') +
- ', val)',
- 'end']);
- }
- var code = functionName + '(' + list + ', ' + value + ')\n';
- return code;
- } else { // `where` = 'FROM_END'
- if (mode == 'SET') {
- var functionName = Blockly.Lua.provideFunction_(
- 'list_set_from_end',
- ['function ' + Blockly.Lua.FUNCTION_NAME_PLACEHOLDER_ +
- '(t, index, val)',
- ' t[#t + 1 - index] = val',
- 'end']);
- } else { // `mode` == 'INSERT'
- var functionName = Blockly.Lua.provideFunction_(
- 'list_insert_from_end',
- ['function ' + Blockly.Lua.FUNCTION_NAME_PLACEHOLDER_ +
- '(t, index, val)',
- ' table.insert(t, #t + 1 - index, val)',
- 'end']);
- }
- var code = functionName + '(' + list + ', ' + at + ', ' + value + ')\n';
- return code;
- }
- } else {
- // It's okay to have multiple references to the list.
- if (mode == 'SET') {
- var code = list + '[' + getIndex_(list, where, at) + '] = ' + value;
- } else { // `mode` == 'INSERT'
- // LAST is a special case, because we want to insert
- // *after* not *before*, the existing last element.
- var code = 'table.insert(' + list + ', ' +
- (getIndex_(list, where, at) + (where == 'LAST' ? ' + 1' : '')) +
- ', ' + value + ')';
- }
- return code + '\n';
+ // We can use multiple statements.
+ var listVar = Blockly.Lua.variableDB_.getDistinctName(
+ 'tmp_list', Blockly.Variables.NAME_TYPE);
+ code = listVar + ' = ' + list + '\n';
+ list = listVar;
}
+ if (mode == 'SET') {
+ code += list + '[' + getIndex_(list, where, at) + '] = ' + value;
+ } else { // `mode` == 'INSERT'
+ // LAST is a special case, because we want to insert
+ // *after* not *before*, the existing last element.
+ code += 'table.insert(' + list + ', ' +
+ (getIndex_(list, where, at) + (where == 'LAST' ? ' + 1' : '')) +
+ ', ' + value + ')';
+ }
+ return code + '\n';
};
Blockly.Lua['lists_getSublist'] = function(block) {
// Get sublist.
var list = Blockly.Lua.valueToCode(block, 'LIST',
- Blockly.Lua.ORDER_HIGH) || '({})';
+ Blockly.Lua.ORDER_NONE) || '{}';
var where1 = block.getFieldValue('WHERE1');
var where2 = block.getFieldValue('WHERE2');
var at1 = Blockly.Lua.valueToCode(block, 'AT1',
- Blockly.Lua.ORDER_ADDITIVE) || '1';
+ Blockly.Lua.ORDER_NONE) || '1';
var at2 = Blockly.Lua.valueToCode(block, 'AT2',
- Blockly.Lua.ORDER_ADDITIVE) || '1';
+ Blockly.Lua.ORDER_NONE) || '1';
var getIndex_ = Blockly.Lua.lists.getIndex_;
var functionName = Blockly.Lua.provideFunction_(
- 'list_sublist_' + Blockly.Lua.lists.gensym_(),
- ['function ' + Blockly.Lua.FUNCTION_NAME_PLACEHOLDER_ + '(source)',
+ 'list_sublist_' + where1.toLowerCase() + '_' + where2.toLowerCase(),
+ ['function ' + Blockly.Lua.FUNCTION_NAME_PLACEHOLDER_ + '(source' +
+ // The value for 'FROM_END' and'FROM_START' depends on `at` so
+ // we add it as a parameter.
+ ((where1 == 'FROM_END' || where1 == 'FROM_START') ? ', at1' : '') +
+ ((where2 == 'FROM_END' || where2 == 'FROM_START') ? ', at2' : '') +
+ ')',
' local t = {}',
- ' local start = ' + getIndex_('source', where1, at1),
- ' local finish = ' + getIndex_('source', where2, at2),
+ ' local start = ' + getIndex_('source', where1, 'at1'),
+ ' local finish = ' + getIndex_('source', where2, 'at2'),
' for i = start, finish do',
' table.insert(t, source[i])',
' end',
' return t',
'end']);
- var code = functionName + '(' + list + ')';
+ var code = functionName + '(' + list +
+ // The value for 'FROM_END' and 'FROM_START' depends on `at` so we
+ // pass it.
+ ((where1 == 'FROM_END' || where1 == 'FROM_START') ? ', ' + at1 : '') +
+ ((where2 == 'FROM_END' || where2 == 'FROM_START') ? ', ' + at2 : '') +
+ ')';
return [code, Blockly.Lua.ORDER_HIGH];
};
Blockly.Lua['lists_sort'] = function(block) {
// Block for sorting a list.
- var listCode = Blockly.Lua.valueToCode(
- block, 'LIST', Blockly.Lua.ORDER_HIGH) || '({})';
+ var list = Blockly.Lua.valueToCode(
+ block, 'LIST', Blockly.Lua.ORDER_NONE) || '{}';
var direction = block.getFieldValue('DIRECTION') === '1' ? 1 : -1;
var type = block.getFieldValue('TYPE');
@@ -357,26 +318,26 @@ Blockly.Lua['lists_sort'] = function(block) {
'end']);
var code = functionName +
- '(' + listCode + ',"' + type + '", ' + direction + ')';
+ '(' + list + ',"' + type + '", ' + direction + ')';
return [code, Blockly.Lua.ORDER_HIGH];
};
Blockly.Lua['lists_split'] = function(block) {
// Block for splitting text into a list, or joining a list into text.
- var value_input = Blockly.Lua.valueToCode(block, 'INPUT',
+ var input = Blockly.Lua.valueToCode(block, 'INPUT',
Blockly.Lua.ORDER_NONE);
- var value_delim = Blockly.Lua.valueToCode(block, 'DELIM',
+ var delimiter = Blockly.Lua.valueToCode(block, 'DELIM',
Blockly.Lua.ORDER_NONE) || '\'\'';
var mode = block.getFieldValue('MODE');
var functionName;
if (mode == 'SPLIT') {
- if (!value_input) {
- value_input = '\'\'';
+ if (!input) {
+ input = '\'\'';
}
functionName = Blockly.Lua.provideFunction_(
'list_string_split',
['function ' + Blockly.Lua.FUNCTION_NAME_PLACEHOLDER_ +
- '(input, delim)',
+ '(input, delim)',
' local t = {}',
' local pos = 1',
' while true do',
@@ -392,13 +353,13 @@ Blockly.Lua['lists_split'] = function(block) {
' return t',
'end']);
} else if (mode == 'JOIN') {
- if (!value_input) {
- value_input = '({})';
+ if (!input) {
+ input = '{}';
}
functionName = 'table.concat';
} else {
throw 'Unknown mode: ' + mode;
}
- var code = functionName + '(' + value_input + ', ' + value_delim + ')';
+ var code = functionName + '(' + input + ', ' + delimiter + ')';
return [code, Blockly.Lua.ORDER_HIGH];
};
diff --git a/generators/lua/procedures.js b/generators/lua/procedures.js
index 9bdcc416b..b6d6cdda1 100644
--- a/generators/lua/procedures.js
+++ b/generators/lua/procedures.js
@@ -51,8 +51,8 @@ Blockly.Lua['procedures_defreturn'] = function(block) {
branch = '';
}
var args = [];
- for (var x = 0; x < block.arguments_.length; x++) {
- args[x] = Blockly.Lua.variableDB_.getName(block.arguments_[x],
+ for (var i = 0; i < block.arguments_.length; i++) {
+ args[i] = Blockly.Lua.variableDB_.getName(block.arguments_[i],
Blockly.Variables.NAME_TYPE);
}
var code = 'function ' + funcName + '(' + args.join(', ') + ')\n' +
@@ -73,8 +73,8 @@ Blockly.Lua['procedures_callreturn'] = function(block) {
var funcName = Blockly.Lua.variableDB_.getName(
block.getFieldValue('NAME'), Blockly.Procedures.NAME_TYPE);
var args = [];
- for (var x = 0; x < block.arguments_.length; x++) {
- args[x] = Blockly.Lua.valueToCode(block, 'ARG' + x,
+ for (var i = 0; i < block.arguments_.length; i++) {
+ args[i] = Blockly.Lua.valueToCode(block, 'ARG' + i,
Blockly.Lua.ORDER_NONE) || 'nil';
}
var code = funcName + '(' + args.join(', ') + ')';
@@ -86,8 +86,8 @@ Blockly.Lua['procedures_callnoreturn'] = function(block) {
var funcName = Blockly.Lua.variableDB_.getName(
block.getFieldValue('NAME'), Blockly.Procedures.NAME_TYPE);
var args = [];
- for (var x = 0; x < block.arguments_.length; x++) {
- args[x] = Blockly.Lua.valueToCode(block, 'ARG' + x,
+ for (var i = 0; i < block.arguments_.length; i++) {
+ args[i] = Blockly.Lua.valueToCode(block, 'ARG' + i,
Blockly.Lua.ORDER_NONE) || 'nil';
}
var code = funcName + '(' + args.join(', ') + ')\n';
diff --git a/generators/lua/text.js b/generators/lua/text.js
index 8a6a02702..74efba4a2 100644
--- a/generators/lua/text.js
+++ b/generators/lua/text.js
@@ -40,24 +40,24 @@ Blockly.Lua['text_join'] = function(block) {
if (block.itemCount_ == 0) {
return ['\'\'', Blockly.Lua.ORDER_ATOMIC];
} else if (block.itemCount_ == 1) {
- var argument0 = Blockly.Lua.valueToCode(block, 'ADD0',
+ var element = Blockly.Lua.valueToCode(block, 'ADD0',
Blockly.Lua.ORDER_NONE) || '\'\'';
- var code = argument0;
+ var code = 'tostring(' + element + ')';
return [code, Blockly.Lua.ORDER_HIGH];
} else if (block.itemCount_ == 2) {
- var argument0 = Blockly.Lua.valueToCode(block, 'ADD0',
- Blockly.Lua.ORDER_NONE) || '\'\'';
- var argument1 = Blockly.Lua.valueToCode(block, 'ADD1',
- Blockly.Lua.ORDER_NONE) || '\'\'';
- var code = argument0 + ' .. ' + argument1;
- return [code, Blockly.Lua.ORDER_UNARY];
+ var element0 = Blockly.Lua.valueToCode(block, 'ADD0',
+ Blockly.Lua.ORDER_CONCATENATION) || '\'\'';
+ var element1 = Blockly.Lua.valueToCode(block, 'ADD1',
+ Blockly.Lua.ORDER_CONCATENATION) || '\'\'';
+ var code = element0 + ' .. ' + element1;
+ return [code, Blockly.Lua.ORDER_CONCATENATION];
} else {
- var code = [];
- for (var n = 0; n < block.itemCount_; n++) {
- code[n] = Blockly.Lua.valueToCode(block, 'ADD' + n,
+ var elements = [];
+ for (var i = 0; i < block.itemCount_; i++) {
+ elements[i] = Blockly.Lua.valueToCode(block, 'ADD' + i,
Blockly.Lua.ORDER_NONE) || '\'\'';
}
- code = 'table.concat({' + code.join(', ') + '})';
+ var code = 'table.concat({' + elements.join(', ') + '})';
return [code, Blockly.Lua.ORDER_HIGH];
}
};
@@ -66,32 +66,30 @@ Blockly.Lua['text_append'] = function(block) {
// Append to a variable in place.
var varName = Blockly.Lua.variableDB_.getName(
block.getFieldValue('VAR'), Blockly.Variables.NAME_TYPE);
- var argument0 = Blockly.Lua.valueToCode(block, 'TEXT',
- Blockly.Lua.ORDER_NONE) || '\'\'';
- return varName + ' = ' + varName + ' .. ' + argument0 + '\n';
+ var value = Blockly.Lua.valueToCode(block, 'TEXT',
+ Blockly.Lua.ORDER_CONCATENATION) || '\'\'';
+ return varName + ' = ' + varName + ' .. ' + value + '\n';
};
Blockly.Lua['text_length'] = function(block) {
// String or array length.
- var argument0 = Blockly.Lua.valueToCode(block, 'VALUE',
- Blockly.Lua.ORDER_HIGH) || '\'\'';
- return ['#' + argument0, Blockly.Lua.ORDER_HIGH];
+ var text = Blockly.Lua.valueToCode(block, 'VALUE',
+ Blockly.Lua.ORDER_UNARY) || '\'\'';
+ return ['#' + text, Blockly.Lua.ORDER_UNARY];
};
Blockly.Lua['text_isEmpty'] = function(block) {
// Is the string null or array empty?
- var argument0 = Blockly.Lua.valueToCode(block, 'VALUE',
- Blockly.Lua.ORDER_HIGH) || '\'\'';
- return ['#' + argument0 + ' == 0', Blockly.Lua.ORDER_RELATIONAL];
+ var text = Blockly.Lua.valueToCode(block, 'VALUE',
+ Blockly.Lua.ORDER_UNARY) || '\'\'';
+ return ['#' + text + ' == 0', Blockly.Lua.ORDER_RELATIONAL];
};
Blockly.Lua['text_indexOf'] = function(block) {
// Search the text for a substring.
- var operator = block.getFieldValue('END') == 'FIRST' ?
- 'indexOf' : 'lastIndexOf';
- var substr = Blockly.Lua.valueToCode(block, 'FIND',
+ var substring = Blockly.Lua.valueToCode(block, 'FIND',
Blockly.Lua.ORDER_NONE) || '\'\'';
- var str = Blockly.Lua.valueToCode(block, 'VALUE',
+ var text = Blockly.Lua.valueToCode(block, 'VALUE',
Blockly.Lua.ORDER_NONE) || '\'\'';
if (block.getFieldValue('END') == 'FIRST') {
var functionName = Blockly.Lua.provideFunction_(
@@ -118,7 +116,7 @@ Blockly.Lua['text_indexOf'] = function(block) {
' return 0',
'end']);
}
- var code = functionName + '(' + str + ', ' + substr + ')';
+ var code = functionName + '(' + text + ', ' + substring + ')';
return [code, Blockly.Lua.ORDER_HIGH];
};
@@ -126,8 +124,9 @@ Blockly.Lua['text_charAt'] = function(block) {
// Get letter at index.
// Note: Until January 2013 this block did not have the WHERE input.
var where = block.getFieldValue('WHERE') || 'FROM_START';
- var at = Blockly.Lua.valueToCode(block, 'AT',
- Blockly.Lua.ORDER_UNARY) || '1';
+ var atOrder = (where == 'FROM_END') ? Blockly.Lua.ORDER_UNARY :
+ Blockly.Lua.ORDER_NONE;
+ var at = Blockly.Lua.valueToCode(block, 'AT', atOrder) || '1';
var text = Blockly.Lua.valueToCode(block, 'VALUE',
Blockly.Lua.ORDER_NONE) || '\'\'';
var code;
@@ -176,8 +175,9 @@ Blockly.Lua['text_getSubstring'] = function(block) {
// Get start index.
var where1 = block.getFieldValue('WHERE1');
- var at1 = Blockly.Lua.valueToCode(block, 'AT1',
- Blockly.Lua.ORDER_UNARY) || '1';
+ var at1Order = (where1 == 'FROM_END') ? Blockly.Lua.ORDER_UNARY :
+ Blockly.Lua.ORDER_NONE;
+ var at1 = Blockly.Lua.valueToCode(block, 'AT1', at1Order) || '1';
if (where1 == 'FIRST') {
var start = 1;
} else if (where1 == 'FROM_START') {
@@ -190,8 +190,9 @@ Blockly.Lua['text_getSubstring'] = function(block) {
// Get end index.
var where2 = block.getFieldValue('WHERE2');
- var at2 = Blockly.Lua.valueToCode(block, 'AT2',
- Blockly.Lua.ORDER_UNARY) || '1';
+ var at2Order = (where2 == 'FROM_END') ? Blockly.Lua.ORDER_UNARY :
+ Blockly.Lua.ORDER_NONE;
+ var at2 = Blockly.Lua.valueToCode(block, 'AT2', at2Order) || '1';
if (where2 == 'LAST') {
var end = -1;
} else if (where2 == 'FROM_START') {
@@ -208,7 +209,7 @@ Blockly.Lua['text_getSubstring'] = function(block) {
Blockly.Lua['text_changeCase'] = function(block) {
// Change capitalization.
var operator = block.getFieldValue('CASE');
- var argument0 = Blockly.Lua.valueToCode(block, 'TEXT',
+ var text = Blockly.Lua.valueToCode(block, 'TEXT',
Blockly.Lua.ORDER_NONE) || '\'\'';
if (operator == 'UPPERCASE') {
var functionName = 'string.upper';
@@ -238,7 +239,7 @@ Blockly.Lua['text_changeCase'] = function(block) {
' return table.concat(buf)',
'end']);
}
- var code = functionName + '(' + argument0 + ')';
+ var code = functionName + '(' + text + ')';
return [code, Blockly.Lua.ORDER_HIGH];
};
@@ -258,9 +259,9 @@ Blockly.Lua['text_trim'] = function(block) {
Blockly.Lua['text_print'] = function(block) {
// Print statement.
- var argument0 = Blockly.Lua.valueToCode(block, 'TEXT',
+ var msg = Blockly.Lua.valueToCode(block, 'TEXT',
Blockly.Lua.ORDER_NONE) || '\'\'';
- return 'print(' + argument0 + ')\n';
+ return 'print(' + msg + ')\n';
};
Blockly.Lua['text_prompt_ext'] = function(block) {
diff --git a/generators/php.js b/generators/php.js
index d935cda1b..02e89e809 100644
--- a/generators/php.js
+++ b/generators/php.js
@@ -44,44 +44,98 @@ Blockly.PHP = new Blockly.Generator('PHP');
*/
Blockly.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,' +
+ '__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__');
+ '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
*/
-Blockly.PHP.ORDER_ATOMIC = 0; // 0 "" ...
-Blockly.PHP.ORDER_CLONE = 1; // clone
-Blockly.PHP.ORDER_NEW = 1; // new
-Blockly.PHP.ORDER_MEMBER = 2; // ()
-Blockly.PHP.ORDER_FUNCTION_CALL = 2; // ()
-Blockly.PHP.ORDER_INCREMENT = 3; // ++
-Blockly.PHP.ORDER_DECREMENT = 3; // --
-Blockly.PHP.ORDER_LOGICAL_NOT = 4; // !
-Blockly.PHP.ORDER_BITWISE_NOT = 4; // ~
-Blockly.PHP.ORDER_UNARY_PLUS = 4; // +
-Blockly.PHP.ORDER_UNARY_NEGATION = 4; // -
-Blockly.PHP.ORDER_MULTIPLICATION = 5; // *
-Blockly.PHP.ORDER_DIVISION = 5; // /
-Blockly.PHP.ORDER_MODULUS = 5; // %
-Blockly.PHP.ORDER_ADDITION = 6; // +
-Blockly.PHP.ORDER_SUBTRACTION = 6; // -
-Blockly.PHP.ORDER_BITWISE_SHIFT = 7; // << >> >>>
-Blockly.PHP.ORDER_RELATIONAL = 8; // < <= > >=
-Blockly.PHP.ORDER_IN = 8; // in
-Blockly.PHP.ORDER_INSTANCEOF = 8; // instanceof
-Blockly.PHP.ORDER_EQUALITY = 9; // == != === !==
-Blockly.PHP.ORDER_BITWISE_AND = 10; // &
-Blockly.PHP.ORDER_BITWISE_XOR = 11; // ^
-Blockly.PHP.ORDER_BITWISE_OR = 12; // |
-Blockly.PHP.ORDER_CONDITIONAL = 13; // ?:
-Blockly.PHP.ORDER_ASSIGNMENT = 14; // = += -= *= /= %= <<= >>= ...
-Blockly.PHP.ORDER_LOGICAL_AND = 15; // &&
-Blockly.PHP.ORDER_LOGICAL_OR = 16; // ||
-Blockly.PHP.ORDER_COMMA = 17; // ,
-Blockly.PHP.ORDER_NONE = 99; // (...)
+Blockly.PHP.ORDER_ATOMIC = 0; // 0 "" ...
+Blockly.PHP.ORDER_CLONE = 1; // clone
+Blockly.PHP.ORDER_NEW = 1; // new
+Blockly.PHP.ORDER_MEMBER = 2.1; // []
+Blockly.PHP.ORDER_FUNCTION_CALL = 2.2; // ()
+Blockly.PHP.ORDER_POWER = 3; // **
+Blockly.PHP.ORDER_INCREMENT = 4; // ++
+Blockly.PHP.ORDER_DECREMENT = 4; // --
+Blockly.PHP.ORDER_BITWISE_NOT = 4; // ~
+Blockly.PHP.ORDER_CAST = 4; // (int) (float) (string) (array) ...
+Blockly.PHP.ORDER_SUPPRESS_ERROR = 4; // @
+Blockly.PHP.ORDER_INSTANCEOF = 5; // instanceof
+Blockly.PHP.ORDER_LOGICAL_NOT = 6; // !
+Blockly.PHP.ORDER_UNARY_PLUS = 7.1; // +
+Blockly.PHP.ORDER_UNARY_NEGATION = 7.2; // -
+Blockly.PHP.ORDER_MULTIPLICATION = 8.1; // *
+Blockly.PHP.ORDER_DIVISION = 8.2; // /
+Blockly.PHP.ORDER_MODULUS = 8.3; // %
+Blockly.PHP.ORDER_ADDITION = 9.1; // +
+Blockly.PHP.ORDER_SUBTRACTION = 9.2; // -
+Blockly.PHP.ORDER_STRING_CONCAT = 9.3; // .
+Blockly.PHP.ORDER_BITWISE_SHIFT = 10; // << >>
+Blockly.PHP.ORDER_RELATIONAL = 11; // < <= > >=
+Blockly.PHP.ORDER_EQUALITY = 12; // == != === !== <> <=>
+Blockly.PHP.ORDER_REFERENCE = 13; // &
+Blockly.PHP.ORDER_BITWISE_AND = 13; // &
+Blockly.PHP.ORDER_BITWISE_XOR = 14; // ^
+Blockly.PHP.ORDER_BITWISE_OR = 15; // |
+Blockly.PHP.ORDER_LOGICAL_AND = 16; // &&
+Blockly.PHP.ORDER_LOGICAL_OR = 17; // ||
+Blockly.PHP.ORDER_IF_NULL = 18; // ??
+Blockly.PHP.ORDER_CONDITIONAL = 19; // ?:
+Blockly.PHP.ORDER_ASSIGNMENT = 20; // = += -= *= /= %= <<= >>= ...
+Blockly.PHP.ORDER_LOGICAL_AND_WEAK = 21; // and
+Blockly.PHP.ORDER_LOGICAL_XOR = 22; // xor
+Blockly.PHP.ORDER_LOGICAL_OR_WEAK = 23; // or
+Blockly.PHP.ORDER_COMMA = 24; // ,
+Blockly.PHP.ORDER_NONE = 99; // (...)
+
+/**
+ * List of outer-inner pairings that do NOT require parentheses.
+ * @type {!Array.>}
+ */
+Blockly.PHP.ORDER_OVERRIDES = [
+ // (foo()).bar() -> foo().bar()
+ // (foo())[0] -> foo()[0]
+ [Blockly.PHP.ORDER_MEMBER, Blockly.PHP.ORDER_FUNCTION_CALL],
+ // (foo[0])[1] -> foo[0][1]
+ // (foo.bar).baz -> foo.bar.baz
+ [Blockly.PHP.ORDER_MEMBER, Blockly.PHP.ORDER_MEMBER],
+ // !(!foo) -> !!foo
+ [Blockly.PHP.ORDER_LOGICAL_NOT, Blockly.PHP.ORDER_LOGICAL_NOT],
+ // a * (b * c) -> a * b * c
+ [Blockly.PHP.ORDER_MULTIPLICATION, Blockly.PHP.ORDER_MULTIPLICATION],
+ // a + (b + c) -> a + b + c
+ [Blockly.PHP.ORDER_ADDITION, Blockly.PHP.ORDER_ADDITION],
+ // a && (b && c) -> a && b && c
+ [Blockly.PHP.ORDER_LOGICAL_AND, Blockly.PHP.ORDER_LOGICAL_AND],
+ // a || (b || c) -> a || b || c
+ [Blockly.PHP.ORDER_LOGICAL_OR, Blockly.PHP.ORDER_LOGICAL_OR]
+];
+
+/**
+ * Allow for switching between one and zero based indexing for lists and text,
+ * one based by default.
+ */
+Blockly.PHP.ONE_BASED_INDEXING = true;
/**
* Initialise the database of variable names.
@@ -173,9 +227,9 @@ Blockly.PHP.scrub_ = function(block, code) {
}
// Collect comments for all value arguments.
// Don't collect comments for nested statements.
- for (var x = 0; x < block.inputList.length; x++) {
- if (block.inputList[x].type == Blockly.INPUT_VALUE) {
- var childBlock = block.inputList[x].connection.targetBlock();
+ for (var i = 0; i < block.inputList.length; i++) {
+ if (block.inputList[i].type == Blockly.INPUT_VALUE) {
+ var childBlock = block.inputList[i].connection.targetBlock();
if (childBlock) {
var comment = Blockly.PHP.allNestedComments(childBlock);
if (comment) {
@@ -189,3 +243,66 @@ Blockly.PHP.scrub_ = function(block, code) {
var nextCode = Blockly.PHP.blockToCode(nextBlock);
return commentCode + code + nextCode;
};
+
+/**
+ * Gets a property and adjusts the value while taking into account indexing.
+ * @param {!Blockly.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}
+ */
+Blockly.PHP.getAdjusted = function(block, atId, opt_delta, opt_negate,
+ opt_order) {
+ var delta = opt_delta || 0;
+ var order = opt_order || Blockly.PHP.ORDER_NONE;
+ if (Blockly.PHP.ONE_BASED_INDEXING) {
+ delta--;
+ }
+ var defaultAtIndex = Blockly.PHP.ONE_BASED_INDEXING ? '1' : '0';
+ if (delta > 0) {
+ var at = Blockly.PHP.valueToCode(block, atId,
+ Blockly.PHP.ORDER_ADDITION) || defaultAtIndex;
+ } else if (delta < 0) {
+ var at = Blockly.PHP.valueToCode(block, atId,
+ Blockly.PHP.ORDER_SUBTRACTION) || defaultAtIndex;
+ } else if (opt_negate) {
+ var at = Blockly.PHP.valueToCode(block, atId,
+ Blockly.PHP.ORDER_UNARY_NEGATION) || defaultAtIndex;
+ } else {
+ var at = Blockly.PHP.valueToCode(block, atId, order) ||
+ defaultAtIndex;
+ }
+
+ if (Blockly.isNumber(at)) {
+ // If the index is a naked number, adjust it right now.
+ at = parseFloat(at) + delta;
+ if (opt_negate) {
+ at = -at;
+ }
+ } else {
+ // If the index is dynamic, adjust it in code.
+ if (delta > 0) {
+ at = at + ' + ' + delta;
+ var innerOrder = Blockly.PHP.ORDER_ADDITION;
+ } else if (delta < 0) {
+ at = at + ' - ' + -delta;
+ var innerOrder = Blockly.PHP.ORDER_SUBTRACTION;
+ }
+ if (opt_negate) {
+ if (delta) {
+ at = '-(' + at + ')';
+ } else {
+ at = '-' + at;
+ }
+ var innerOrder = Blockly.PHP.ORDER_UNARY_NEGATION;
+ }
+ innerOrder = Math.floor(innerOrder);
+ order = Math.floor(order);
+ if (innerOrder && order >= innerOrder) {
+ at = '(' + at + ')';
+ }
+ }
+ return at;
+};
diff --git a/generators/php/colour.js b/generators/php/colour.js
index bc1789c35..e73c17a95 100644
--- a/generators/php/colour.js
+++ b/generators/php/colour.js
@@ -39,10 +39,10 @@ Blockly.PHP['colour_random'] = function(block) {
// Generate a random colour.
var functionName = Blockly.PHP.provideFunction_(
'colour_random',
- [ 'function ' + Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_ + '() {',
- ' return \'#\' . str_pad(dechex(mt_rand(0, 0xFFFFFF)), ' +
- '6, \'0\', STR_PAD_LEFT);',
- '}']);
+ ['function ' + Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_ + '() {',
+ ' return \'#\' . str_pad(dechex(mt_rand(0, 0xFFFFFF)), ' +
+ '6, \'0\', STR_PAD_LEFT);',
+ '}']);
var code = functionName + '()';
return [code, Blockly.PHP.ORDER_FUNCTION_CALL];
};
@@ -57,17 +57,17 @@ Blockly.PHP['colour_rgb'] = function(block) {
Blockly.PHP.ORDER_COMMA) || 0;
var functionName = Blockly.PHP.provideFunction_(
'colour_rgb',
- [ 'function ' + Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_ +
+ ['function ' + Blockly.PHP.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);',
- ' $hex = "#";',
- ' $hex .= str_pad(dechex($r), 2, "0", STR_PAD_LEFT);',
- ' $hex .= str_pad(dechex($g), 2, "0", STR_PAD_LEFT);',
- ' $hex .= str_pad(dechex($b), 2, "0", STR_PAD_LEFT);',
- ' return $hex;',
- '}']);
+ ' $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);',
+ ' $hex = \'#\';',
+ ' $hex .= str_pad(dechex($r), 2, \'0\', STR_PAD_LEFT);',
+ ' $hex .= str_pad(dechex($g), 2, \'0\', STR_PAD_LEFT);',
+ ' $hex .= str_pad(dechex($b), 2, \'0\', STR_PAD_LEFT);',
+ ' return $hex;',
+ '}']);
var code = functionName + '(' + red + ', ' + green + ', ' + blue + ')';
return [code, Blockly.PHP.ORDER_FUNCTION_CALL];
};
@@ -82,24 +82,24 @@ Blockly.PHP['colour_blend'] = function(block) {
Blockly.PHP.ORDER_COMMA) || 0.5;
var functionName = Blockly.PHP.provideFunction_(
'colour_blend',
- [ 'function ' + Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_ +
+ ['function ' + Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_ +
'($c1, $c2, $ratio) {',
- ' $ratio = max(min($ratio, 1), 0);',
- ' $r1 = hexdec(substr($c1, 1, 2));',
- ' $g1 = hexdec(substr($c1, 3, 2));',
- ' $b1 = hexdec(substr($c1, 5, 2));',
- ' $r2 = hexdec(substr($c2, 1, 2));',
- ' $g2 = hexdec(substr($c2, 3, 2));',
- ' $b2 = hexdec(substr($c2, 5, 2));',
- ' $r = round($r1 * (1 - $ratio) + $r2 * $ratio);',
- ' $g = round($g1 * (1 - $ratio) + $g2 * $ratio);',
- ' $b = round($b1 * (1 - $ratio) + $b2 * $ratio);',
- ' $hex = "#";',
- ' $hex .= str_pad(dechex($r), 2, "0", STR_PAD_LEFT);',
- ' $hex .= str_pad(dechex($g), 2, "0", STR_PAD_LEFT);',
- ' $hex .= str_pad(dechex($b), 2, "0", STR_PAD_LEFT);',
- ' return $hex;',
- '}']);
+ ' $ratio = max(min($ratio, 1), 0);',
+ ' $r1 = hexdec(substr($c1, 1, 2));',
+ ' $g1 = hexdec(substr($c1, 3, 2));',
+ ' $b1 = hexdec(substr($c1, 5, 2));',
+ ' $r2 = hexdec(substr($c2, 1, 2));',
+ ' $g2 = hexdec(substr($c2, 3, 2));',
+ ' $b2 = hexdec(substr($c2, 5, 2));',
+ ' $r = round($r1 * (1 - $ratio) + $r2 * $ratio);',
+ ' $g = round($g1 * (1 - $ratio) + $g2 * $ratio);',
+ ' $b = round($b1 * (1 - $ratio) + $b2 * $ratio);',
+ ' $hex = \'#\';',
+ ' $hex .= str_pad(dechex($r), 2, \'0\', STR_PAD_LEFT);',
+ ' $hex .= str_pad(dechex($g), 2, \'0\', STR_PAD_LEFT);',
+ ' $hex .= str_pad(dechex($b), 2, \'0\', STR_PAD_LEFT);',
+ ' return $hex;',
+ '}']);
var code = functionName + '(' + c1 + ', ' + c2 + ', ' + ratio + ')';
return [code, Blockly.PHP.ORDER_FUNCTION_CALL];
};
diff --git a/generators/php/lists.js b/generators/php/lists.js
index a406aa6d2..449c31a5e 100644
--- a/generators/php/lists.js
+++ b/generators/php/lists.js
@@ -22,6 +22,17 @@
* @fileoverview Generating PHP for list blocks.
* @author daarond@gmail.com (Daaron Dwyer)
*/
+
+/*
+ * Lists in PHP are known to break when non-variables are passed into blocks
+ * that require a list. PHP, unlike other languages, passes arrays as reference
+ * value instead of value so we are unable to support it to the extent we can
+ * for the other languages.
+ * For example, a ternary operator with two arrays will return the array by
+ * value and that cannot be passed into any of the built-in array functions for
+ * PHP (because only variables can be passed by reference).
+ * ex: end(true ? list1 : list2)
+ */
'use strict';
goog.provide('Blockly.PHP.lists');
@@ -31,37 +42,37 @@ goog.require('Blockly.PHP');
Blockly.PHP['lists_create_empty'] = function(block) {
// Create an empty list.
- return ['array()', Blockly.PHP.ORDER_ATOMIC];
+ return ['array()', Blockly.PHP.ORDER_FUNCTION_CALL];
};
Blockly.PHP['lists_create_with'] = function(block) {
// Create a list with any number of elements of any type.
var code = new Array(block.itemCount_);
- for (var n = 0; n < block.itemCount_; n++) {
- code[n] = Blockly.PHP.valueToCode(block, 'ADD' + n,
+ for (var i = 0; i < block.itemCount_; i++) {
+ code[i] = Blockly.PHP.valueToCode(block, 'ADD' + i,
Blockly.PHP.ORDER_COMMA) || 'null';
}
code = 'array(' + code.join(', ') + ')';
- return [code, Blockly.PHP.ORDER_ATOMIC];
+ return [code, Blockly.PHP.ORDER_FUNCTION_CALL];
};
Blockly.PHP['lists_repeat'] = function(block) {
// Create a list with one element repeated.
var functionName = Blockly.PHP.provideFunction_(
'lists_repeat',
- [ 'function ' + Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_ +
+ ['function ' + Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_ +
'($value, $count) {',
- ' $array = array();',
- ' for ($index = 0; $index < $count; $index++) {',
- ' $array[] = $value;',
- ' }',
- ' return $array;',
- '}']);
- var argument0 = Blockly.PHP.valueToCode(block, 'ITEM',
+ ' $array = array();',
+ ' for ($index = 0; $index < $count; $index++) {',
+ ' $array[] = $value;',
+ ' }',
+ ' return $array;',
+ '}']);
+ var element = Blockly.PHP.valueToCode(block, 'ITEM',
Blockly.PHP.ORDER_COMMA) || 'null';
- var argument1 = Blockly.PHP.valueToCode(block, 'NUM',
+ var repeatCount = Blockly.PHP.valueToCode(block, 'NUM',
Blockly.PHP.ORDER_COMMA) || '0';
- var code = functionName + '(' + argument0 + ', ' + argument1 + ')';
+ var code = functionName + '(' + element + ', ' + repeatCount + ')';
return [code, Blockly.PHP.ORDER_FUNCTION_CALL];
};
@@ -69,16 +80,16 @@ Blockly.PHP['lists_length'] = function(block) {
// String or array length.
var functionName = Blockly.PHP.provideFunction_(
'length',
- [ 'function ' + Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_ + '($value) {',
- ' if (is_string($value)) {',
- ' return strlen($value);',
- ' } else {',
- ' return count($value);',
- ' }',
- '}']);
- var argument0 = Blockly.PHP.valueToCode(block, 'VALUE',
- Blockly.PHP.ORDER_FUNCTION_CALL) || '\'\'';
- return [functionName + '(' + argument0 + ')', Blockly.PHP.ORDER_FUNCTION_CALL];
+ ['function ' + Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_ + '($value) {',
+ ' if (is_string($value)) {',
+ ' return strlen($value);',
+ ' } else {',
+ ' return count($value);',
+ ' }',
+ '}']);
+ var list = Blockly.PHP.valueToCode(block, 'VALUE',
+ Blockly.PHP.ORDER_NONE) || '\'\'';
+ return [functionName + '(' + list + ')', Blockly.PHP.ORDER_FUNCTION_CALL];
};
Blockly.PHP['lists_isEmpty'] = function(block) {
@@ -90,36 +101,42 @@ Blockly.PHP['lists_isEmpty'] = function(block) {
Blockly.PHP['lists_indexOf'] = function(block) {
// Find an item in the list.
- var operator = block.getFieldValue('END') == 'FIRST' ?
- 'indexOf' : 'lastIndexOf';
var argument0 = Blockly.PHP.valueToCode(block, 'FIND',
Blockly.PHP.ORDER_NONE) || '\'\'';
var argument1 = Blockly.PHP.valueToCode(block, 'VALUE',
Blockly.PHP.ORDER_MEMBER) || '[]';
- var functionName;
- if (block.getFieldValue('END') == 'FIRST'){
+ if (Blockly.PHP.ONE_BASED_INDEXING) {
+ var errorIndex = ' 0';
+ var indexAdjustment = ' + 1';
+ } else {
+ var errorIndex = ' -1';
+ var indexAdjustment = '';
+ }
+ if (block.getFieldValue('END') == 'FIRST') {
// indexOf
- functionName = Blockly.PHP.provideFunction_(
+ var functionName = Blockly.PHP.provideFunction_(
'indexOf',
- [ 'function ' + Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_ +
- '($haystack, $needle) {',
- ' for ($index = 0; $index < count($haystack); $index++) {',
- ' if ($haystack[$index] == $needle) return $index + 1;',
- ' }',
- ' return 0;',
- '}']);
+ ['function ' + Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_ +
+ '($haystack, $needle) {',
+ ' for ($index = 0; $index < count($haystack); $index++) {',
+ ' if ($haystack[$index] == $needle) return $index' +
+ indexAdjustment + ';',
+ ' }',
+ ' return ' + errorIndex + ';',
+ '}']);
} else {
// lastIndexOf
- functionName = Blockly.PHP.provideFunction_(
+ var functionName = Blockly.PHP.provideFunction_(
'lastIndexOf',
- [ 'function ' + Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_ +
- '($haystack, $needle) {',
- ' $last = 0;',
- ' for ($index = 0; $index < count($haystack); $index++) {',
- ' if ($haystack[$index] == $needle) $last = $index + 1;',
- ' }',
- ' return $last;',
- '}']);
+ ['function ' + Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_ +
+ '($haystack, $needle) {',
+ ' $last = ' + errorIndex + ';',
+ ' for ($index = 0; $index < count($haystack); $index++) {',
+ ' if ($haystack[$index] == $needle) $last = $index' +
+ indexAdjustment + ';',
+ ' }',
+ ' return $last;',
+ '}']);
}
var code = functionName + '(' + argument1 + ', ' + argument0 + ')';
@@ -130,97 +147,113 @@ Blockly.PHP['lists_getIndex'] = function(block) {
// Get element at index.
var mode = block.getFieldValue('MODE') || 'GET';
var where = block.getFieldValue('WHERE') || 'FROM_START';
- var at = Blockly.PHP.valueToCode(block, 'AT',
- Blockly.PHP.ORDER_UNARY_NEGATION) || '1';
- if (mode == 'GET') {
- var order = Blockly.PHP.ORDER_FUNCTION_CALL;
- } else {
- // List will be an argument in a function call.
- var order = Blockly.PHP.ORDER_COMMA;
- }
- var list = Blockly.PHP.valueToCode(block, 'VALUE', order) || 'array()';
-
- if (where == 'FIRST') {
- if (mode == 'GET') {
- var code = list + '[0]';
- return [code, Blockly.PHP.ORDER_FUNCTION_CALL];
- } else if (mode == 'GET_REMOVE') {
- var code = 'array_shift(' + list + ')';
- return [code, Blockly.PHP.ORDER_FUNCTION_CALL];
- } else if (mode == 'REMOVE') {
- return 'array_shift(' + list + ');\n';
- }
- } else if (where == 'LAST') {
- if (mode == 'GET') {
- var code = 'end(' + list + ')';
- return [code, Blockly.PHP.ORDER_FUNCTION_CALL];
- } else if (mode == 'GET_REMOVE') {
- var code = 'array_pop(' + list + ')';
- return [code, Blockly.PHP.ORDER_FUNCTION_CALL];
- } else if (mode == 'REMOVE') {
- return 'array_pop(' + list + ');\n';
- }
- } else if (where == 'FROM_START') {
- // Blockly uses one-based indicies.
- if (Blockly.isNumber(at)) {
- // If the index is a naked number, decrement it right now.
- at = parseFloat(at) - 1;
- } else {
- // If the index is dynamic, decrement it in code.
- at += ' - 1';
- }
- if (mode == 'GET') {
- var code = list + '[' + at + ']';
- return [code, Blockly.PHP.ORDER_FUNCTION_CALL];
- } else if (mode == 'GET_REMOVE') {
- var code = 'array_splice(' + list + ', ' + at + ', 1)[0]';
- return [code, Blockly.PHP.ORDER_FUNCTION_CALL];
- } else if (mode == 'REMOVE') {
- return 'array_splice(' + list + ', ' + at + ', 1);\n';
- }
- } else if (where == 'FROM_END') {
- if (mode == 'GET') {
- var code = 'array_slice(' + list + ', -' + at + ', 1)[0]';
- return [code, Blockly.PHP.ORDER_FUNCTION_CALL];
- } else if (mode == 'GET_REMOVE' || mode == 'REMOVE') {
- code = 'array_splice(' + list +
- ', count(' + list + ') - ' + at + ', 1)[0]';
- if (mode == 'GET_REMOVE') {
+ switch (where) {
+ case 'FIRST':
+ if (mode == 'GET') {
+ var list = Blockly.PHP.valueToCode(block, 'VALUE',
+ Blockly.PHP.ORDER_MEMBER) || 'array()';
+ var code = list + '[0]';
+ return [code, Blockly.PHP.ORDER_MEMBER];
+ } else if (mode == 'GET_REMOVE') {
+ var list = Blockly.PHP.valueToCode(block, 'VALUE',
+ Blockly.PHP.ORDER_NONE) || 'array()';
+ var code = 'array_shift(' + list + ')';
return [code, Blockly.PHP.ORDER_FUNCTION_CALL];
} else if (mode == 'REMOVE') {
- return code + ';\n';
+ var list = Blockly.PHP.valueToCode(block, 'VALUE',
+ Blockly.PHP.ORDER_NONE) || 'array()';
+ return 'array_shift(' + list + ');\n';
}
- }
- } else if (where == 'RANDOM') {
- if (mode == 'GET'){
- var functionName = Blockly.PHP.provideFunction_(
- 'lists_get_random_item',
- [ 'function ' + Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_ +
- '($list) {',
- ' return $list[rand(0,count($list)-1)];',
- '}']);
- code = functionName + '(' + list + ')';
- return [code, Blockly.PHP.ORDER_FUNCTION_CALL];
- } else if (mode == 'GET_REMOVE'){
- var functionName = Blockly.PHP.provideFunction_(
- 'lists_get_remove_random_item',
- [ 'function ' + Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_ +
- '(&$list) {',
- ' $x = rand(0,count($list)-1);',
- ' unset($list[$x]);',
- ' return array_values($list);',
- '}']);
- code = functionName + '(' + list + ')';
- return [code, Blockly.PHP.ORDER_FUNCTION_CALL];
- } else if (mode == 'REMOVE') {
- var functionName = Blockly.PHP.provideFunction_(
- 'lists_remove_random_item',
- [ 'function ' + Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_ +
- '(&$list) {',
- ' unset($list[rand(0,count($list)-1)]);',
- '}']);
- return functionName + '(' + list + ');\n';
- }
+ break;
+ case 'LAST':
+ if (mode == 'GET') {
+ var list = Blockly.PHP.valueToCode(block, 'VALUE',
+ Blockly.PHP.ORDER_NONE) || 'array()';
+ var code = 'end(' + list + ')';
+ return [code, Blockly.PHP.ORDER_FUNCTION_CALL];
+ } else if (mode == 'GET_REMOVE') {
+ var list = Blockly.PHP.valueToCode(block, 'VALUE',
+ Blockly.PHP.ORDER_NONE) || 'array()';
+ var code = 'array_pop(' + list + ')';
+ return [code, Blockly.PHP.ORDER_FUNCTION_CALL];
+ } else if (mode == 'REMOVE') {
+ var list = Blockly.PHP.valueToCode(block, 'VALUE',
+ Blockly.PHP.ORDER_NONE) || 'array()';
+ return 'array_pop(' + list + ');\n';
+ }
+ break;
+ case 'FROM_START':
+ var at = Blockly.PHP.getAdjusted(block, 'AT');
+ if (mode == 'GET') {
+ var list = Blockly.PHP.valueToCode(block, 'VALUE',
+ Blockly.PHP.ORDER_MEMBER) || 'array()';
+ var code = list + '[' + at + ']';
+ return [code, Blockly.PHP.ORDER_MEMBER];
+ } else if (mode == 'GET_REMOVE') {
+ var list = Blockly.PHP.valueToCode(block, 'VALUE',
+ Blockly.PHP.ORDER_COMMA) || 'array()';
+ var code = 'array_splice(' + list + ', ' + at + ', 1)[0]';
+ return [code, Blockly.PHP.ORDER_FUNCTION_CALL];
+ } else if (mode == 'REMOVE') {
+ var list = Blockly.PHP.valueToCode(block, 'VALUE',
+ Blockly.PHP.ORDER_COMMA) || 'array()';
+ return 'array_splice(' + list + ', ' + at + ', 1);\n';
+ }
+ break;
+ case 'FROM_END':
+ if (mode == 'GET') {
+ var list = Blockly.PHP.valueToCode(block, 'VALUE',
+ Blockly.PHP.ORDER_COMMA) || 'array()';
+ var at = Blockly.PHP.getAdjusted(block, 'AT', 1, true);
+ var code = 'array_slice(' + list + ', ' + at + ', 1)[0]';
+ return [code, Blockly.PHP.ORDER_FUNCTION_CALL];
+ } else if (mode == 'GET_REMOVE' || mode == 'REMOVE') {
+ var list = Blockly.PHP.valueToCode(block, 'VALUE',
+ Blockly.PHP.ORDER_NONE) || 'array()';
+ var at = Blockly.PHP.getAdjusted(block, 'AT', 1, false,
+ Blockly.PHP.ORDER_SUBTRACTION);
+ code = 'array_splice(' + list +
+ ', count(' + list + ') - ' + at + ', 1)[0]';
+ if (mode == 'GET_REMOVE') {
+ return [code, Blockly.PHP.ORDER_FUNCTION_CALL];
+ } else if (mode == 'REMOVE') {
+ return code + ';\n';
+ }
+ }
+ break;
+ case 'RANDOM':
+ var list = Blockly.PHP.valueToCode(block, 'VALUE',
+ Blockly.PHP.ORDER_NONE) || 'array()';
+ if (mode == 'GET') {
+ var functionName = Blockly.PHP.provideFunction_(
+ 'lists_get_random_item',
+ ['function ' + Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_ +
+ '($list) {',
+ ' return $list[rand(0,count($list)-1)];',
+ '}']);
+ code = functionName + '(' + list + ')';
+ return [code, Blockly.PHP.ORDER_FUNCTION_CALL];
+ } else if (mode == 'GET_REMOVE') {
+ var functionName = Blockly.PHP.provideFunction_(
+ 'lists_get_remove_random_item',
+ ['function ' + Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_ +
+ '(&$list) {',
+ ' $x = rand(0,count($list)-1);',
+ ' unset($list[$x]);',
+ ' return array_values($list);',
+ '}']);
+ code = functionName + '(' + list + ')';
+ return [code, Blockly.PHP.ORDER_FUNCTION_CALL];
+ } else if (mode == 'REMOVE') {
+ var functionName = Blockly.PHP.provideFunction_(
+ 'lists_remove_random_item',
+ ['function ' + Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_ +
+ '(&$list) {',
+ ' unset($list[rand(0,count($list)-1)]);',
+ '}']);
+ return functionName + '(' + list + ');\n';
+ }
+ break;
}
throw 'Unhandled combination (lists_getIndex).';
};
@@ -228,18 +261,14 @@ Blockly.PHP['lists_getIndex'] = function(block) {
Blockly.PHP['lists_setIndex'] = function(block) {
// Set element at index.
// Note: Until February 2013 this block did not have MODE or WHERE inputs.
- var list = Blockly.PHP.valueToCode(block, 'LIST',
- Blockly.PHP.ORDER_MEMBER) || 'array()';
var mode = block.getFieldValue('MODE') || 'GET';
var where = block.getFieldValue('WHERE') || 'FROM_START';
- var at = Blockly.PHP.valueToCode(block, 'AT',
- Blockly.PHP.ORDER_NONE) || '1';
var value = Blockly.PHP.valueToCode(block, 'TO',
Blockly.PHP.ORDER_ASSIGNMENT) || 'null';
// Cache non-trivial values to variables to prevent repeated look-ups.
// Closure, which accesses and modifies 'list'.
function cacheList() {
- if (list.match(/^\w+$/)) {
+ if (list.match(/^\$\w+$/)) {
return '';
}
var listVar = Blockly.PHP.variableDB_.getDistinctName(
@@ -248,68 +277,83 @@ Blockly.PHP['lists_setIndex'] = function(block) {
list = listVar;
return code;
}
- if (where == 'FIRST') {
- if (mode == 'SET') {
- return list + '[0] = ' + value + ';\n';
- } else if (mode == 'INSERT') {
- return 'array_unshift(' + list + ', ' + value + ');\n';
- }
- } else if (where == 'LAST') {
- if (mode == 'SET') {
- var functionName = Blockly.PHP.provideFunction_(
- 'lists_set_last_item',
- [ 'function ' + Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_ +
- '(&$list, $value) {',
- ' $list[count($list) - 1] = $value;',
- '}']);
- return functionName + '(' + list + ', ' + value + ');\n';
- } else if (mode == 'INSERT') {
- return 'array_push(' + list + ', ' + value + ');\n';
- }
- } else if (where == 'FROM_START') {
- // Blockly uses one-based indicies.
- if (Blockly.isNumber(at)) {
- // If the index is a naked number, decrement it right now.
- at = parseFloat(at) - 1;
- } else {
- // If the index is dynamic, decrement it in code.
- at += ' - 1';
- }
- if (mode == 'SET') {
- return list + '[' + at + '] = ' + value + ';\n';
- } else if (mode == 'INSERT') {
- return 'array_splice(' + list + ', ' + at + ', 0, ' + value + ');\n';
- }
- } else if (where == 'FROM_END') {
- if (mode == 'SET') {
- var functionName = Blockly.PHP.provideFunction_(
- 'lists_set_from_end',
- [ 'function ' + Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_ +
- '(&$list, $at, $value) {',
- ' $list[count($list) - $at] = $value;',
- '}']);
- return functionName + '(' + list + ', ' + at + ', ' + value + ');\n';
- } else if (mode == 'INSERT') {
- var functionName = Blockly.PHP.provideFunction_(
- 'lists_insert_from_end',
- [ 'function ' + Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_ +
- '(&$list, $at, $value) {',
- ' return array_splice($list, count($list) - $at, 0, $value);',
- '}']);
- return functionName + '(' + list + ', ' + at + ', ' + value + ');\n';
- }
- } else if (where == 'RANDOM') {
- var code = cacheList();
- var xVar = Blockly.PHP.variableDB_.getDistinctName(
- 'tmp_x', Blockly.Variables.NAME_TYPE);
- code += xVar + ' = rand(0, count(' + list + ')-1);\n';
- if (mode == 'SET') {
- code += list + '[' + xVar + '] = ' + value + ';\n';
- return code;
- } else if (mode == 'INSERT') {
- code += 'array_splice(' + list + ', ' + xVar + ', 0, ' + value + ');\n';
- return code;
- }
+ switch (where) {
+ case 'FIRST':
+ if (mode == 'SET') {
+ var list = Blockly.PHP.valueToCode(block, 'LIST',
+ Blockly.PHP.ORDER_MEMBER) || 'array()';
+ return list + '[0] = ' + value + ';\n';
+ } else if (mode == 'INSERT') {
+ var list = Blockly.PHP.valueToCode(block, 'LIST',
+ Blockly.PHP.ORDER_COMMA) || 'array()';
+ return 'array_unshift(' + list + ', ' + value + ');\n';
+ }
+ break;
+ case 'LAST':
+ var list = Blockly.PHP.valueToCode(block, 'LIST',
+ Blockly.PHP.ORDER_COMMA) || 'array()';
+ if (mode == 'SET') {
+ var functionName = Blockly.PHP.provideFunction_(
+ 'lists_set_last_item',
+ ['function ' + Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_ +
+ '(&$list, $value) {',
+ ' $list[count($list) - 1] = $value;',
+ '}']);
+ return functionName + '(' + list + ', ' + value + ');\n';
+ } else if (mode == 'INSERT') {
+ return 'array_push(' + list + ', ' + value + ');\n';
+ }
+ break;
+ case 'FROM_START':
+ var at = Blockly.PHP.getAdjusted(block, 'AT');
+ if (mode == 'SET') {
+ var list = Blockly.PHP.valueToCode(block, 'LIST',
+ Blockly.PHP.ORDER_MEMBER) || 'array()';
+ return list + '[' + at + '] = ' + value + ';\n';
+ } else if (mode == 'INSERT') {
+ var list = Blockly.PHP.valueToCode(block, 'LIST',
+ Blockly.PHP.ORDER_COMMA) || 'array()';
+ return 'array_splice(' + list + ', ' + at + ', 0, ' + value + ');\n';
+ }
+ break;
+ case 'FROM_END':
+ var list = Blockly.PHP.valueToCode(block, 'LIST',
+ Blockly.PHP.ORDER_COMMA) || 'array()';
+ var at = Blockly.PHP.getAdjusted(block, 'AT', 1);
+ if (mode == 'SET') {
+ var functionName = Blockly.PHP.provideFunction_(
+ 'lists_set_from_end',
+ ['function ' + Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_ +
+ '(&$list, $at, $value) {',
+ ' $list[count($list) - $at] = $value;',
+ '}']);
+ return functionName + '(' + list + ', ' + at + ', ' + value + ');\n';
+ } else if (mode == 'INSERT') {
+ var functionName = Blockly.PHP.provideFunction_(
+ 'lists_insert_from_end',
+ ['function ' + Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_ +
+ '(&$list, $at, $value) {',
+ ' return array_splice($list, count($list) - $at, 0, $value);',
+ '}']);
+ return functionName + '(' + list + ', ' + at + ', ' + value + ');\n';
+ }
+ break;
+ case 'RANDOM':
+ var list = Blockly.PHP.valueToCode(block, 'LIST',
+ Blockly.PHP.ORDER_REFERENCE) || 'array()';
+ var code = cacheList();
+ var xVar = Blockly.PHP.variableDB_.getDistinctName(
+ 'tmp_x', Blockly.Variables.NAME_TYPE);
+ code += xVar + ' = rand(0, count(' + list + ')-1);\n';
+ if (mode == 'SET') {
+ code += list + '[' + xVar + '] = ' + value + ';\n';
+ return code;
+ } else if (mode == 'INSERT') {
+ code += 'array_splice(' + list + ', ' + xVar + ', 0, ' + value +
+ ');\n';
+ return code;
+ }
+ break;
}
throw 'Unhandled combination (lists_setIndex).';
};
@@ -317,44 +361,90 @@ Blockly.PHP['lists_setIndex'] = function(block) {
Blockly.PHP['lists_getSublist'] = function(block) {
// Get sublist.
var list = Blockly.PHP.valueToCode(block, 'LIST',
- Blockly.PHP.ORDER_MEMBER) || 'array()';
+ Blockly.PHP.ORDER_COMMA) || 'array()';
var where1 = block.getFieldValue('WHERE1');
var where2 = block.getFieldValue('WHERE2');
- var at1 = Blockly.PHP.valueToCode(block, 'AT1',
- Blockly.PHP.ORDER_NONE) || '1';
- var at2 = Blockly.PHP.valueToCode(block, 'AT2',
- Blockly.PHP.ORDER_NONE) || '1';
if (where1 == 'FIRST' && where2 == 'LAST') {
var code = list;
+ } else if (list.match(/^\$\w+$/) ||
+ (where1 != 'FROM_END' && where2 == 'FROM_START')) {
+ // If the list is a simple value or doesn't require a call for length, don't
+ // generate a helper function.
+ switch (where1) {
+ case 'FROM_START':
+ var at1 = Blockly.PHP.getAdjusted(block, 'AT1');
+ break;
+ case 'FROM_END':
+ var at1 = Blockly.PHP.getAdjusted(block, 'AT1', 1, false,
+ Blockly.PHP.ORDER_SUBTRACTION);
+ at1 = 'count(' + list + ') - ' + at1;
+ break;
+ case 'FIRST':
+ var at1 = '0';
+ break;
+ default:
+ throw 'Unhandled option (lists_getSublist).';
+ }
+ switch (where2) {
+ case 'FROM_START':
+ var at2 = Blockly.PHP.getAdjusted(block, 'AT2', 0, false,
+ Blockly.PHP.ORDER_SUBTRACTION);
+ var length = at2 + ' - ';
+ if (Blockly.isNumber(String(at1)) || String(at1).match(/^\(.+\)$/)) {
+ length += at1;
+ } else {
+ length += '(' + at1 + ')';
+ }
+ length += ' + 1';
+ break;
+ case 'FROM_END':
+ var at2 = Blockly.PHP.getAdjusted(block, 'AT2', 0, false,
+ Blockly.PHP.ORDER_SUBTRACTION);
+ var length = 'count(' + list + ') - ' + at2 + ' - ';
+ if (Blockly.isNumber(String(at1)) || String(at1).match(/^\(.+\)$/)) {
+ length += at1;
+ } else {
+ length += '(' + at1 + ')';
+ }
+ break;
+ case 'LAST':
+ var length = 'count(' + list + ') - ';
+ if (Blockly.isNumber(String(at1)) || String(at1).match(/^\(.+\)$/)) {
+ length += at1;
+ } else {
+ length += '(' + at1 + ')';
+ }
+ break;
+ default:
+ throw 'Unhandled option (lists_getSublist).';
+ }
+ code = 'array_slice(' + list + ', ' + at1 + ', ' + length + ')';
} else {
+ var at1 = Blockly.PHP.getAdjusted(block, 'AT1');
+ var at2 = Blockly.PHP.getAdjusted(block, 'AT2');
var functionName = Blockly.PHP.provideFunction_(
'lists_get_sublist',
- [ 'function ' + Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_ +
+ ['function ' + Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_ +
'($list, $where1, $at1, $where2, $at2) {',
- ' if ($where2 == \'FROM_START\') {',
- ' $at2--;',
- ' } else if ($where2 == \'FROM_END\') {',
- ' $at2 = $at2 - $at1;',
- ' } else if ($where2 == \'FIRST\') {',
- ' $at2 = 0;',
- ' } else if ($where2 == \'LAST\') {',
- ' $at2 = count($list);',
- ' } else {',
- ' throw \'Unhandled option (lists_getSublist).\';',
- ' }',
- ' if ($where1 == \'FROM_START\') {',
- ' $at1--;',
- ' } else if ($where1 == \'FROM_END\') {',
- ' $at1 = count($list) - $at1;',
- ' } else if ($where1 == \'FIRST\') {',
- ' $at1 = 0;',
- ' } else if ($where1 == \'LAST\') {',
- ' $at1 = count($list) - 1;',
- ' } else {',
- ' throw \'Unhandled option (lists_getSublist).\';',
- ' }',
- ' return array_slice($list, $at1, $at2);',
- '}']);
+ ' if ($where1 == \'FROM_END\') {',
+ ' $at1 = count($list) - 1 - $at1;',
+ ' } else if ($where1 == \'FIRST\') {',
+ ' $at1 = 0;',
+ ' } else if ($where1 != \'FROM_START\'){',
+ ' throw new Exception(\'Unhandled option (lists_get_sublist).\');',
+ ' }',
+ ' $length = 0;',
+ ' if ($where2 == \'FROM_START\') {',
+ ' $length = $at2 - $at1 + 1;',
+ ' } else if ($where2 == \'FROM_END\') {',
+ ' $length = count($list) - $at1 - $at2;',
+ ' } else if ($where2 == \'LAST\') {',
+ ' $length = count($list) - $at1;',
+ ' } else {',
+ ' throw new Exception(\'Unhandled option (lists_get_sublist).\');',
+ ' }',
+ ' return array_slice($list, $at1, $length);',
+ '}']);
var code = functionName + '(' + list + ', \'' +
where1 + '\', ' + at1 + ', \'' + where2 + '\', ' + at2 + ')';
}
@@ -364,26 +454,26 @@ Blockly.PHP['lists_getSublist'] = function(block) {
Blockly.PHP['lists_sort'] = function(block) {
// Block for sorting a list.
var listCode = Blockly.PHP.valueToCode(block, 'LIST',
- Blockly.PHP.ORDER_FUNCTION_CALL) || 'array()';
+ Blockly.PHP.ORDER_COMMA) || 'array()';
var direction = block.getFieldValue('DIRECTION') === '1' ? 1 : -1;
var type = block.getFieldValue('TYPE');
var functionName = Blockly.PHP.provideFunction_(
- 'lists_sort', [
- 'function ' + Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_ +
- '($list, $type, $direction) {',
- ' $sortCmpFuncs = array(',
- ' "NUMERIC" => "strnatcasecmp",',
- ' "TEXT" => "strcmp",',
- ' "IGNORE_CASE" => "strcasecmp"',
- ' );',
- ' $sortCmp = $sortCmpFuncs[$type];',
- ' $list2 = $list;', // Clone list.
- ' usort($list2, $sortCmp);',
- ' if ($direction == -1) {',
- ' $list2 = array_reverse($list2);',
- ' }',
- ' return $list2;',
- '}']);
+ 'lists_sort',
+ ['function ' + Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_ +
+ '($list, $type, $direction) {',
+ ' $sortCmpFuncs = array(',
+ ' "NUMERIC" => "strnatcasecmp",',
+ ' "TEXT" => "strcmp",',
+ ' "IGNORE_CASE" => "strcasecmp"',
+ ' );',
+ ' $sortCmp = $sortCmpFuncs[$type];',
+ ' $list2 = $list;', // Clone list.
+ ' usort($list2, $sortCmp);',
+ ' if ($direction == -1) {',
+ ' $list2 = array_reverse($list2);',
+ ' }',
+ ' return $list2;',
+ '}']);
var sortCode = functionName +
'(' + listCode + ', "' + type + '", ' + direction + ')';
return [sortCode, Blockly.PHP.ORDER_FUNCTION_CALL];
@@ -392,9 +482,9 @@ Blockly.PHP['lists_sort'] = function(block) {
Blockly.PHP['lists_split'] = function(block) {
// Block for splitting text into a list, or joining a list into text.
var value_input = Blockly.PHP.valueToCode(block, 'INPUT',
- Blockly.PHP.ORDER_MEMBER);
+ Blockly.PHP.ORDER_COMMA);
var value_delim = Blockly.PHP.valueToCode(block, 'DELIM',
- Blockly.PHP.ORDER_NONE) || '\'\'';
+ Blockly.PHP.ORDER_COMMA) || '\'\'';
var mode = block.getFieldValue('MODE');
if (mode == 'SPLIT') {
if (!value_input) {
diff --git a/generators/php/math.js b/generators/php/math.js
index f0bb9fa79..7789ba8fe 100644
--- a/generators/php/math.js
+++ b/generators/php/math.js
@@ -47,20 +47,14 @@ Blockly.PHP['math_arithmetic'] = function(block) {
'MINUS': [' - ', Blockly.PHP.ORDER_SUBTRACTION],
'MULTIPLY': [' * ', Blockly.PHP.ORDER_MULTIPLICATION],
'DIVIDE': [' / ', Blockly.PHP.ORDER_DIVISION],
- 'POWER': [null, Blockly.PHP.ORDER_COMMA] // Handle power separately.
+ 'POWER': [' ** ', Blockly.PHP.ORDER_POWER]
};
var tuple = OPERATORS[block.getFieldValue('OP')];
var operator = tuple[0];
var order = tuple[1];
var argument0 = Blockly.PHP.valueToCode(block, 'A', order) || '0';
var argument1 = Blockly.PHP.valueToCode(block, 'B', order) || '0';
- var code;
- // Power in PHP requires a special case since it has no operator.
- if (!operator) {
- code = 'pow(' + argument0 + ', ' + argument1 + ')';
- return [code, Blockly.PHP.ORDER_FUNCTION_CALL];
- }
- code = argument0 + operator + argument1;
+ var code = argument0 + operator + argument1;
return [code, order];
};
@@ -172,25 +166,25 @@ Blockly.PHP['math_number_property'] = function(block) {
// Prime is a special case as it is not a one-liner test.
var functionName = Blockly.PHP.provideFunction_(
'math_isPrime',
- [ 'function ' + Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_ + '($n) {',
- ' // https://en.wikipedia.org/wiki/Primality_test#Naive_methods',
- ' if ($n == 2 || $n == 3) {',
- ' return true;',
- ' }',
- ' // False if n is NaN, negative, is 1, or not whole.',
- ' // And false if n is divisible by 2 or 3.',
- ' if (!is_numeric($n) || $n <= 1 || $n % 1 != 0 || $n % 2 == 0 ||' +
- ' $n % 3 == 0) {',
- ' return false;',
- ' }',
- ' // Check all the numbers of form 6k +/- 1, up to sqrt(n).',
- ' for ($x = 6; $x <= sqrt($n) + 1; $x += 6) {',
- ' if ($n % ($x - 1) == 0 || $n % ($x + 1) == 0) {',
- ' return false;',
- ' }',
- ' }',
- ' return true;',
- '}']);
+ ['function ' + Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_ + '($n) {',
+ ' // https://en.wikipedia.org/wiki/Primality_test#Naive_methods',
+ ' if ($n == 2 || $n == 3) {',
+ ' return true;',
+ ' }',
+ ' // False if n is NaN, negative, is 1, or not whole.',
+ ' // And false if n is divisible by 2 or 3.',
+ ' if (!is_numeric($n) || $n <= 1 || $n % 1 != 0 || $n % 2 == 0 ||' +
+ ' $n % 3 == 0) {',
+ ' return false;',
+ ' }',
+ ' // Check all the numbers of form 6k +/- 1, up to sqrt(n).',
+ ' for ($x = 6; $x <= sqrt($n) + 1; $x += 6) {',
+ ' if ($n % ($x - 1) == 0 || $n % ($x + 1) == 0) {',
+ ' return false;',
+ ' }',
+ ' }',
+ ' return true;',
+ '}']);
code = functionName + '(' + number_to_check + ')';
return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL];
}
@@ -256,10 +250,10 @@ Blockly.PHP['math_on_list'] = function(block) {
case 'AVERAGE':
var functionName = Blockly.PHP.provideFunction_(
'math_mean',
- [ 'function ' + Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_ +
+ ['function ' + Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_ +
'($myList) {',
- ' return array_sum($myList) / count($myList);',
- '}']);
+ ' return array_sum($myList) / count($myList);',
+ '}']);
list = Blockly.PHP.valueToCode(block, 'LIST',
Blockly.PHP.ORDER_NONE) || 'array()';
code = functionName + '(' + list + ')';
@@ -267,12 +261,13 @@ Blockly.PHP['math_on_list'] = function(block) {
case 'MEDIAN':
var functionName = Blockly.PHP.provideFunction_(
'math_median',
- [ 'function ' + Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_ +
+ ['function ' + Blockly.PHP.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;',
- '}']);
+ ' 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 = Blockly.PHP.valueToCode(block, 'LIST',
Blockly.PHP.ORDER_NONE) || '[]';
code = functionName + '(' + list + ')';
@@ -283,13 +278,14 @@ Blockly.PHP['math_on_list'] = function(block) {
// Mode of [3, 'x', 'x', 1, 1, 2, '3'] -> ['x', 1].
var functionName = Blockly.PHP.provideFunction_(
'math_modes',
- [ 'function ' + Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_ +
+ ['function ' + Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_ +
'($values) {',
- ' $v = array_count_values($values);',
- ' arsort($v);',
- ' foreach($v as $k => $v){$total = $k; break;}',
- ' return array($total);',
- '}']);
+ ' if (empty($values)) return array();',
+ ' $counts = array_count_values($values);',
+ ' arsort($counts); // Sort counts in descending order',
+ ' $modes = array_keys($counts, current($counts), true);',
+ ' return $modes;',
+ '}']);
list = Blockly.PHP.valueToCode(block, 'LIST',
Blockly.PHP.ORDER_NONE) || '[]';
code = functionName + '(' + list + ')';
@@ -297,14 +293,15 @@ Blockly.PHP['math_on_list'] = function(block) {
case 'STD_DEV':
var functionName = Blockly.PHP.provideFunction_(
'math_standard_deviation',
- [ 'function ' + Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_ +
- '($numbers) {',
- ' $n = count($numbers);',
- ' if (!$n) return null;',
- ' $mean = array_sum($numbers) / count($numbers);',
- ' foreach($numbers as $key => $num) $devs[$key] = pow($num - $mean, 2);',
- ' return sqrt(array_sum($devs) / (count($devs) - 1));',
- '}']);
+ ['function ' + Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_ +
+ '($numbers) {',
+ ' $n = count($numbers);',
+ ' if (!$n) return null;',
+ ' $mean = array_sum($numbers) / count($numbers);',
+ ' foreach($numbers as $key => $num) $devs[$key] = ' +
+ 'pow($num - $mean, 2);',
+ ' return sqrt(array_sum($devs) / (count($devs) - 1));',
+ '}']);
list = Blockly.PHP.valueToCode(block, 'LIST',
Blockly.PHP.ORDER_NONE) || '[]';
code = functionName + '(' + list + ')';
@@ -312,11 +309,11 @@ Blockly.PHP['math_on_list'] = function(block) {
case 'RANDOM':
var functionName = Blockly.PHP.provideFunction_(
'math_random_list',
- [ 'function ' + Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_ +
+ ['function ' + Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_ +
'($list) {',
- ' $x = rand(0, count($list)-1);',
- ' return $list[$x];',
- '}']);
+ ' $x = rand(0, count($list)-1);',
+ ' return $list[$x];',
+ '}']);
list = Blockly.PHP.valueToCode(block, 'LIST',
Blockly.PHP.ORDER_NONE) || '[]';
code = functionName + '(' + list + ')';
@@ -358,13 +355,13 @@ Blockly.PHP['math_random_int'] = function(block) {
Blockly.PHP.ORDER_COMMA) || '0';
var functionName = Blockly.PHP.provideFunction_(
'math_random_int',
- [ 'function ' + Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_ +
+ ['function ' + Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_ +
'($a, $b) {',
- ' if ($a > $b) {',
- ' return rand($b, $a);',
- ' }',
- ' return rand($a, $b);',
- '}']);
+ ' if ($a > $b) {',
+ ' return rand($b, $a);',
+ ' }',
+ ' return rand($a, $b);',
+ '}']);
var code = functionName + '(' + argument0 + ', ' + argument1 + ')';
return [code, Blockly.PHP.ORDER_FUNCTION_CALL];
};
diff --git a/generators/php/procedures.js b/generators/php/procedures.js
index 1fd4cc872..0dc56d7cb 100644
--- a/generators/php/procedures.js
+++ b/generators/php/procedures.js
@@ -63,8 +63,8 @@ Blockly.PHP['procedures_defreturn'] = function(block) {
returnValue = ' return ' + returnValue + ';\n';
}
var args = [];
- for (var x = 0; x < block.arguments_.length; x++) {
- args[x] = Blockly.PHP.variableDB_.getName(block.arguments_[x],
+ for (var i = 0; i < block.arguments_.length; i++) {
+ args[i] = Blockly.PHP.variableDB_.getName(block.arguments_[i],
Blockly.Variables.NAME_TYPE);
}
var code = 'function ' + funcName + '(' + args.join(', ') + ') {\n' +
@@ -85,8 +85,8 @@ Blockly.PHP['procedures_callreturn'] = function(block) {
var funcName = Blockly.PHP.variableDB_.getName(
block.getFieldValue('NAME'), Blockly.Procedures.NAME_TYPE);
var args = [];
- for (var x = 0; x < block.arguments_.length; x++) {
- args[x] = Blockly.PHP.valueToCode(block, 'ARG' + x,
+ for (var i = 0; i < block.arguments_.length; i++) {
+ args[i] = Blockly.PHP.valueToCode(block, 'ARG' + i,
Blockly.PHP.ORDER_COMMA) || 'null';
}
var code = funcName + '(' + args.join(', ') + ')';
@@ -98,8 +98,8 @@ Blockly.PHP['procedures_callnoreturn'] = function(block) {
var funcName = Blockly.PHP.variableDB_.getName(
block.getFieldValue('NAME'), Blockly.Procedures.NAME_TYPE);
var args = [];
- for (var x = 0; x < block.arguments_.length; x++) {
- args[x] = Blockly.PHP.valueToCode(block, 'ARG' + x,
+ for (var i = 0; i < block.arguments_.length; i++) {
+ args[i] = Blockly.PHP.valueToCode(block, 'ARG' + i,
Blockly.PHP.ORDER_COMMA) || 'null';
}
var code = funcName + '(' + args.join(', ') + ');\n';
diff --git a/generators/php/text.js b/generators/php/text.js
index 3960ab011..efc0f2de3 100644
--- a/generators/php/text.js
+++ b/generators/php/text.js
@@ -37,28 +37,27 @@ Blockly.PHP['text'] = function(block) {
Blockly.PHP['text_join'] = function(block) {
// Create a string made up of any number of elements of any type.
- var code;
if (block.itemCount_ == 0) {
return ['\'\'', Blockly.PHP.ORDER_ATOMIC];
} else if (block.itemCount_ == 1) {
- var argument0 = Blockly.PHP.valueToCode(block, 'ADD0',
+ var element = Blockly.PHP.valueToCode(block, 'ADD0',
Blockly.PHP.ORDER_NONE) || '\'\'';
- code = argument0;
+ var code = element;
return [code, Blockly.PHP.ORDER_FUNCTION_CALL];
} else if (block.itemCount_ == 2) {
- var argument0 = Blockly.PHP.valueToCode(block, 'ADD0',
+ var element0 = Blockly.PHP.valueToCode(block, 'ADD0',
Blockly.PHP.ORDER_NONE) || '\'\'';
- var argument1 = Blockly.PHP.valueToCode(block, 'ADD1',
+ var element1 = Blockly.PHP.valueToCode(block, 'ADD1',
Blockly.PHP.ORDER_NONE) || '\'\'';
- code = argument0 + ' . ' + argument1;
+ var code = element0 + ' . ' + element1;
return [code, Blockly.PHP.ORDER_ADDITION];
} else {
- code = new Array(block.itemCount_);
- for (var n = 0; n < block.itemCount_; n++) {
- code[n] = Blockly.PHP.valueToCode(block, 'ADD' + n,
+ var elements = new Array(block.itemCount_);
+ for (var i = 0; i < block.itemCount_; i++) {
+ elements[i] = Blockly.PHP.valueToCode(block, 'ADD' + i,
Blockly.PHP.ORDER_COMMA) || '\'\'';
}
- code = 'implode(\'\', array(' + code.join(',') + '))';
+ var code = 'implode(\'\', array(' + elements.join(',') + '))';
return [code, Blockly.PHP.ORDER_FUNCTION_CALL];
}
};
@@ -67,89 +66,89 @@ Blockly.PHP['text_append'] = function(block) {
// Append to a variable in place.
var varName = Blockly.PHP.variableDB_.getName(
block.getFieldValue('VAR'), Blockly.Variables.NAME_TYPE);
- var argument0 = Blockly.PHP.valueToCode(block, 'TEXT',
- Blockly.PHP.ORDER_NONE) || '\'\'';
- return varName + ' .= ' + argument0 + ';\n';
+ var value = Blockly.PHP.valueToCode(block, 'TEXT',
+ Blockly.PHP.ORDER_ASSIGNMENT) || '\'\'';
+ return varName + ' .= ' + value + ';\n';
};
Blockly.PHP['text_length'] = function(block) {
// String or array length.
var functionName = Blockly.PHP.provideFunction_(
'length',
- [ 'function ' + Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_ + '($value) {',
- ' if (is_string($value)) {',
- ' return strlen($value);',
- ' } else {',
- ' return count($value);',
- ' }',
- '}']);
- var argument0 = Blockly.PHP.valueToCode(block, 'VALUE',
- Blockly.PHP.ORDER_FUNCTION_CALL) || '\'\'';
- return [functionName + '(' + argument0 + ')', Blockly.PHP.ORDER_FUNCTION_CALL];
+ ['function ' + Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_ + '($value) {',
+ ' if (is_string($value)) {',
+ ' return strlen($value);',
+ ' } else {',
+ ' return count($value);',
+ ' }',
+ '}']);
+ var text = Blockly.PHP.valueToCode(block, 'VALUE',
+ Blockly.PHP.ORDER_NONE) || '\'\'';
+ return [functionName + '(' + text + ')', Blockly.PHP.ORDER_FUNCTION_CALL];
};
Blockly.PHP['text_isEmpty'] = function(block) {
// Is the string null or array empty?
- var argument0 = Blockly.PHP.valueToCode(block, 'VALUE',
- Blockly.PHP.ORDER_FUNCTION_CALL) || '\'\'';
- return ['empty(' + argument0 + ')', Blockly.PHP.ORDER_FUNCTION_CALL];
+ var text = Blockly.PHP.valueToCode(block, 'VALUE',
+ Blockly.PHP.ORDER_NONE) || '\'\'';
+ return ['empty(' + text + ')', Blockly.PHP.ORDER_FUNCTION_CALL];
};
Blockly.PHP['text_indexOf'] = function(block) {
// Search the text for a substring.
var operator = block.getFieldValue('END') == 'FIRST' ?
'strpos' : 'strrpos';
- var argument0 = Blockly.PHP.valueToCode(block, 'FIND',
- Blockly.PHP.ORDER_FUNCTION_CALL) || '\'\'';
- var argument1 = Blockly.PHP.valueToCode(block, 'VALUE',
- Blockly.PHP.ORDER_FUNCTION_CALL) || '\'\'';
-
+ var substring = Blockly.PHP.valueToCode(block, 'FIND',
+ Blockly.PHP.ORDER_NONE) || '\'\'';
+ var text = Blockly.PHP.valueToCode(block, 'VALUE',
+ Blockly.PHP.ORDER_NONE) || '\'\'';
+ if (Blockly.PHP.ONE_BASED_INDEXING) {
+ var errorIndex = ' 0';
+ var indexAdjustment = ' + 1';
+ } else {
+ var errorIndex = ' -1';
+ var indexAdjustment = '';
+ }
var functionName = Blockly.PHP.provideFunction_(
block.getFieldValue('END') == 'FIRST' ?
'text_indexOf' : 'text_lastIndexOf',
- [ 'function ' + Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_ +
+ ['function ' + Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_ +
'($text, $search) {',
- ' $pos = ' + operator + '($text, $search);',
- ' return $pos === false ? 0 : $pos + 1;',
- '}']);
- var code = functionName + '(' + argument1 + ', ' + argument0 + ')';
+ ' $pos = ' + operator + '($text, $search);',
+ ' return $pos === false ? ' + errorIndex + ' : $pos' +
+ indexAdjustment + ';',
+ '}']);
+ var code = functionName + '(' + text + ', ' + substring + ')';
return [code, Blockly.PHP.ORDER_FUNCTION_CALL];
};
Blockly.PHP['text_charAt'] = function(block) {
// Get letter at index.
var where = block.getFieldValue('WHERE') || 'FROM_START';
- var at = Blockly.PHP.valueToCode(block, 'AT',
- Blockly.PHP.ORDER_FUNCTION_CALL) || '0';
- var text = Blockly.PHP.valueToCode(block, 'VALUE',
- Blockly.PHP.ORDER_FUNCTION_CALL) || '\'\'';
+ var textOrder = (where == 'RANDOM') ? Blockly.PHP.ORDER_NONE :
+ Blockly.PHP.ORDER_COMMA;
+ var text = Blockly.PHP.valueToCode(block, 'VALUE', textOrder) || '\'\'';
switch (where) {
case 'FIRST':
- var code = text + '[0]';
+ var code = 'substr(' + text + ', 0, 1)';
return [code, Blockly.PHP.ORDER_FUNCTION_CALL];
case 'LAST':
- var code = 'substr(' + text + ', -1, 1)';
+ var code = 'substr(' + text + ', -1)';
return [code, Blockly.PHP.ORDER_FUNCTION_CALL];
case 'FROM_START':
- // Blockly uses one-based indicies.
- if (Blockly.isNumber(at)) {
- // If the index is a naked number, decrement it right now.
- at = parseFloat(at) - 1;
- } else {
- // If the index is dynamic, decrement it in code.
- at += ' - 1';
- }
+ var at = Blockly.PHP.getAdjusted(block, 'AT');
var code = 'substr(' + text + ', ' + at + ', 1)';
return [code, Blockly.PHP.ORDER_FUNCTION_CALL];
case 'FROM_END':
- var code = 'substr(' + text + ', -' + at + ', 1)';
+ var at = Blockly.PHP.getAdjusted(block, 'AT', 1, true);
+ var code = 'substr(' + text + ', ' + at + ', 1)';
return [code, Blockly.PHP.ORDER_FUNCTION_CALL];
case 'RANDOM':
var functionName = Blockly.PHP.provideFunction_(
'text_random_letter',
- [ 'function ' + Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_ + '($text) {',
- ' return $text[rand(0, strlen($text) - 1)];',
- '}']);
+ ['function ' + Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_ + '($text) {',
+ ' return $text[rand(0, strlen($text) - 1)];',
+ '}']);
code = functionName + '(' + text + ')';
return [code, Blockly.PHP.ORDER_FUNCTION_CALL];
}
@@ -162,37 +161,34 @@ Blockly.PHP['text_getSubstring'] = function(block) {
Blockly.PHP.ORDER_FUNCTION_CALL) || '\'\'';
var where1 = block.getFieldValue('WHERE1');
var where2 = block.getFieldValue('WHERE2');
- var at1 = Blockly.PHP.valueToCode(block, 'AT1',
- Blockly.PHP.ORDER_FUNCTION_CALL) || '0';
- var at2 = Blockly.PHP.valueToCode(block, 'AT2',
- Blockly.PHP.ORDER_FUNCTION_CALL) || '0';
if (where1 == 'FIRST' && where2 == 'LAST') {
var code = text;
} else {
+ var at1 = Blockly.PHP.getAdjusted(block, 'AT1');
+ var at2 = Blockly.PHP.getAdjusted(block, 'AT2');
var functionName = Blockly.PHP.provideFunction_(
'text_get_substring',
- [ 'function ' + Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_ +
+ ['function ' + Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_ +
'($text, $where1, $at1, $where2, $at2) {',
- ' if ($where2 == \'FROM_START\') {',
- ' $at2--;',
- ' } else if ($where2 == \'FROM_END\') {',
- ' $at2 = $at2 - $at1;',
- ' } else if ($where2 == \'FIRST\') {',
- ' $at2 = 0;',
- ' } else if ($where2 == \'LAST\') {',
- ' $at2 = strlen($text);',
- ' } else { $at2 = 0; }',
- ' if ($where1 == \'FROM_START\') {',
- ' $at1--;',
- ' } else if ($where1 == \'FROM_END\') {',
- ' $at1 = strlen($text) - $at1;',
- ' } else if ($where1 == \'FIRST\') {',
- ' $at1 = 0;',
- ' } else if ($where1 == \'LAST\') {',
- ' $at1 = strlen($text) - 1;',
- ' } else { $at1 = 0; }',
- ' return substr($text, $at1, $at2);',
- '}']);
+ ' if ($where1 == \'FROM_END\') {',
+ ' $at1 = strlen($text) - 1 - $at1;',
+ ' } else if ($where1 == \'FIRST\') {',
+ ' $at1 = 0;',
+ ' } else if ($where1 != \'FROM_START\'){',
+ ' throw new Exception(\'Unhandled option (text_get_substring).\');',
+ ' }',
+ ' $length = 0;',
+ ' if ($where2 == \'FROM_START\') {',
+ ' $length = $at2 - $at1 + 1;',
+ ' } else if ($where2 == \'FROM_END\') {',
+ ' $length = strlen($text) - $at1 - $at2;',
+ ' } else if ($where2 == \'LAST\') {',
+ ' $length = strlen($text) - $at1;',
+ ' } else {',
+ ' throw new Exception(\'Unhandled option (text_get_substring).\');',
+ ' }',
+ ' return substr($text, $at1, $length);',
+ '}']);
var code = functionName + '(' + text + ', \'' +
where1 + '\', ' + at1 + ', \'' + where2 + '\', ' + at2 + ')';
}
@@ -201,19 +197,14 @@ Blockly.PHP['text_getSubstring'] = function(block) {
Blockly.PHP['text_changeCase'] = function(block) {
// Change capitalization.
- var code;
+ var text = Blockly.PHP.valueToCode(block, 'TEXT',
+ Blockly.PHP.ORDER_NONE) || '\'\'';
if (block.getFieldValue('CASE') == 'UPPERCASE') {
- var argument0 = Blockly.PHP.valueToCode(block, 'TEXT',
- Blockly.PHP.ORDER_FUNCTION_CALL) || '\'\'';
- code = 'strtoupper(' + argument0 + ')';
+ var code = 'strtoupper(' + text + ')';
} else if (block.getFieldValue('CASE') == 'LOWERCASE') {
- var argument0 = Blockly.PHP.valueToCode(block, 'TEXT',
- Blockly.PHP.ORDER_FUNCTION_CALL) || '\'\'';
- code = 'strtolower(' + argument0 + ')';
+ var code = 'strtolower(' + text + ')';
} else if (block.getFieldValue('CASE') == 'TITLECASE') {
- var argument0 = Blockly.PHP.valueToCode(block, 'TEXT',
- Blockly.PHP.ORDER_FUNCTION_CALL) || '\'\'';
- code = 'ucwords(strtolower(' + argument0 + '))';
+ var code = 'ucwords(strtolower(' + text + '))';
}
return [code, Blockly.PHP.ORDER_FUNCTION_CALL];
};
@@ -226,16 +217,16 @@ Blockly.PHP['text_trim'] = function(block) {
'BOTH': 'trim'
};
var operator = OPERATORS[block.getFieldValue('MODE')];
- var argument0 = Blockly.PHP.valueToCode(block, 'TEXT',
+ var text = Blockly.PHP.valueToCode(block, 'TEXT',
Blockly.PHP.ORDER_NONE) || '\'\'';
- return [ operator + '(' + argument0 + ')', Blockly.PHP.ORDER_FUNCTION_CALL];
+ return [operator + '(' + text + ')', Blockly.PHP.ORDER_FUNCTION_CALL];
};
Blockly.PHP['text_print'] = function(block) {
// Print statement.
- var argument0 = Blockly.PHP.valueToCode(block, 'TEXT',
+ var msg = Blockly.PHP.valueToCode(block, 'TEXT',
Blockly.PHP.ORDER_NONE) || '\'\'';
- return 'print(' + argument0 + ');\n';
+ return 'print(' + msg + ');\n';
};
Blockly.PHP['text_prompt_ext'] = function(block) {
diff --git a/generators/php/variables.js b/generators/php/variables.js
index dd68f4ead..466774b3f 100644
--- a/generators/php/variables.js
+++ b/generators/php/variables.js
@@ -43,4 +43,4 @@ Blockly.PHP['variables_set'] = function(block) {
var varName = Blockly.PHP.variableDB_.getName(
block.getFieldValue('VAR'), Blockly.Variables.NAME_TYPE);
return varName + ' = ' + argument0 + ';\n';
-};
\ No newline at end of file
+};
diff --git a/generators/python.js b/generators/python.js
index 2e77c0753..679093db1 100644
--- a/generators/python.js
+++ b/generators/python.js
@@ -46,11 +46,22 @@ Blockly.Python.addReservedWords(
// import keyword
// print ','.join(keyword.kwlist)
// http://docs.python.org/reference/lexical_analysis.html#keywords
- 'and,as,assert,break,class,continue,def,del,elif,else,except,exec,finally,for,from,global,if,import,in,is,lambda,not,or,pass,print,raise,return,try,while,with,yield,' +
+ 'and,as,assert,break,class,continue,def,del,elif,else,except,exec,' +
+ 'finally,for,from,global,if,import,in,is,lambda,not,or,pass,print,raise,' +
+ 'return,try,while,with,yield,' +
//http://docs.python.org/library/constants.html
- 'True,False,None,NotImplemented,Ellipsis,__debug__,quit,exit,copyright,license,credits,' +
+ 'True,False,None,NotImplemented,Ellipsis,__debug__,quit,exit,copyright,' +
+ 'license,credits,' +
// http://docs.python.org/library/functions.html
- 'abs,divmod,input,open,staticmethod,all,enumerate,int,ord,str,any,eval,isinstance,pow,sum,basestring,execfile,issubclass,print,super,bin,file,iter,property,tuple,bool,filter,len,range,type,bytearray,float,list,raw_input,unichr,callable,format,locals,reduce,unicode,chr,frozenset,long,reload,vars,classmethod,getattr,map,repr,xrange,cmp,globals,max,reversed,zip,compile,hasattr,memoryview,round,__import__,complex,hash,min,set,apply,delattr,help,next,setattr,buffer,dict,hex,object,slice,coerce,dir,id,oct,sorted,intern');
+ 'abs,divmod,input,open,staticmethod,all,enumerate,int,ord,str,any,eval,' +
+ 'isinstance,pow,sum,basestring,execfile,issubclass,print,super,bin,file,' +
+ 'iter,property,tuple,bool,filter,len,range,type,bytearray,float,list,' +
+ 'raw_input,unichr,callable,format,locals,reduce,unicode,chr,frozenset,' +
+ 'long,reload,vars,classmethod,getattr,map,repr,xrange,cmp,globals,max,' +
+ 'reversed,zip,compile,hasattr,memoryview,round,__import__,complex,hash,' +
+ 'min,set,apply,delattr,help,next,setattr,buffer,dict,hex,object,slice,' +
+ 'coerce,dir,id,oct,sorted,intern'
+);
/**
* Order of operation ENUMs.
@@ -79,6 +90,12 @@ Blockly.Python.ORDER_CONDITIONAL = 15; // if else
Blockly.Python.ORDER_LAMBDA = 16; // lambda
Blockly.Python.ORDER_NONE = 99; // (...)
+/**
+ * Allow for switching between one and zero based indexing for lists and text,
+ * one based by default.
+ */
+Blockly.Python.ONE_BASED_INDEXING = true;
+
/**
* List of outer-inner pairings that do NOT require parentheses.
* @type {!Array.>}
@@ -213,9 +230,9 @@ Blockly.Python.scrub_ = function(block, code) {
}
// Collect comments for all value arguments.
// Don't collect comments for nested statements.
- for (var x = 0; x < block.inputList.length; x++) {
- if (block.inputList[x].type == Blockly.INPUT_VALUE) {
- var childBlock = block.inputList[x].connection.targetBlock();
+ for (var i = 0; i < block.inputList.length; i++) {
+ if (block.inputList[i].type == Blockly.INPUT_VALUE) {
+ var childBlock = block.inputList[i].connection.targetBlock();
if (childBlock) {
var comment = Blockly.Python.allNestedComments(childBlock);
if (comment) {
@@ -229,3 +246,45 @@ Blockly.Python.scrub_ = function(block, code) {
var nextCode = Blockly.Python.blockToCode(nextBlock);
return commentCode + code + nextCode;
};
+
+/**
+ * Gets a property and adjusts the value, taking into account indexing, and
+ * casts to an integer.
+ * @param {!Blockly.Block} block The block.
+ * @param {string} atId The property ID of the element to get.
+ * @param {number=} opt_delta Value to add.
+ * @param {boolean=} opt_negate Whether to negate the value.
+ * @return {string|number}
+ */
+Blockly.Python.getAdjustedInt = function(block, atId, opt_delta, opt_negate) {
+ var delta = opt_delta || 0;
+ if (Blockly.Python.ONE_BASED_INDEXING) {
+ delta--;
+ }
+ var defaultAtIndex = Blockly.Python.ONE_BASED_INDEXING ? '1' : '0';
+ var atOrder = delta ? Blockly.Python.ORDER_ADDITIVE :
+ Blockly.Python.ORDER_NONE;
+ var at = Blockly.Python.valueToCode(block, atId, atOrder) || defaultAtIndex;
+
+ if (Blockly.isNumber(at)) {
+ // If the index is a naked number, adjust it right now.
+ at = parseInt(at, 10) + delta;
+ if (opt_negate) {
+ at = -at;
+ }
+ } else {
+ // If the index is dynamic, adjust it in code.
+ if (delta > 0) {
+ at = 'int(' + at + ' + ' + delta + ')';
+ } else if (delta < 0) {
+ at = 'int(' + at + ' - ' + -delta + ')';
+ } else {
+ at = 'int(' + at + ')';
+ }
+ if (opt_negate) {
+ at = '-' + at;
+ }
+ }
+ return at;
+};
+
diff --git a/generators/python/colour.js b/generators/python/colour.js
index 49505ac86..68666a89b 100644
--- a/generators/python/colour.js
+++ b/generators/python/colour.js
@@ -46,11 +46,11 @@ Blockly.Python['colour_rgb'] = function(block) {
// Compose a colour from RGB components expressed as percentages.
var functionName = Blockly.Python.provideFunction_(
'colour_rgb',
- [ 'def ' + Blockly.Python.FUNCTION_NAME_PLACEHOLDER_ + '(r, g, b):',
- ' r = round(min(100, max(0, r)) * 2.55)',
- ' g = round(min(100, max(0, g)) * 2.55)',
- ' b = round(min(100, max(0, b)) * 2.55)',
- ' return \'#%02x%02x%02x\' % (r, g, b)']);
+ ['def ' + Blockly.Python.FUNCTION_NAME_PLACEHOLDER_ + '(r, g, b):',
+ ' r = round(min(100, max(0, r)) * 2.55)',
+ ' g = round(min(100, max(0, g)) * 2.55)',
+ ' b = round(min(100, max(0, b)) * 2.55)',
+ ' return \'#%02x%02x%02x\' % (r, g, b)']);
var r = Blockly.Python.valueToCode(block, 'RED',
Blockly.Python.ORDER_NONE) || 0;
var g = Blockly.Python.valueToCode(block, 'GREEN',
diff --git a/generators/python/lists.js b/generators/python/lists.js
index e43e31d5e..b831d4d2f 100644
--- a/generators/python/lists.js
+++ b/generators/python/lists.js
@@ -36,66 +36,75 @@ Blockly.Python['lists_create_empty'] = function(block) {
Blockly.Python['lists_create_with'] = function(block) {
// Create a list with any number of elements of any type.
- var code = new Array(block.itemCount_);
- for (var n = 0; n < block.itemCount_; n++) {
- code[n] = Blockly.Python.valueToCode(block, 'ADD' + n,
+ var elements = new Array(block.itemCount_);
+ for (var i = 0; i < block.itemCount_; i++) {
+ elements[i] = Blockly.Python.valueToCode(block, 'ADD' + i,
Blockly.Python.ORDER_NONE) || 'None';
}
- code = '[' + code.join(', ') + ']';
+ var code = '[' + elements.join(', ') + ']';
return [code, Blockly.Python.ORDER_ATOMIC];
};
Blockly.Python['lists_repeat'] = function(block) {
// Create a list with one element repeated.
- var argument0 = Blockly.Python.valueToCode(block, 'ITEM',
+ var item = Blockly.Python.valueToCode(block, 'ITEM',
Blockly.Python.ORDER_NONE) || 'None';
- var argument1 = Blockly.Python.valueToCode(block, 'NUM',
+ var times = Blockly.Python.valueToCode(block, 'NUM',
Blockly.Python.ORDER_MULTIPLICATIVE) || '0';
- var code = '[' + argument0 + '] * ' + argument1;
+ var code = '[' + item + '] * ' + times;
return [code, Blockly.Python.ORDER_MULTIPLICATIVE];
};
Blockly.Python['lists_length'] = function(block) {
// String or array length.
- var argument0 = Blockly.Python.valueToCode(block, 'VALUE',
+ var list = Blockly.Python.valueToCode(block, 'VALUE',
Blockly.Python.ORDER_NONE) || '[]';
- return ['len(' + argument0 + ')', Blockly.Python.ORDER_FUNCTION_CALL];
+ return ['len(' + list + ')', Blockly.Python.ORDER_FUNCTION_CALL];
};
Blockly.Python['lists_isEmpty'] = function(block) {
// Is the string null or array empty?
- var argument0 = Blockly.Python.valueToCode(block, 'VALUE',
+ var list = Blockly.Python.valueToCode(block, 'VALUE',
Blockly.Python.ORDER_NONE) || '[]';
- var code = 'not len(' + argument0 + ')';
+ var code = 'not len(' + list + ')';
return [code, Blockly.Python.ORDER_LOGICAL_NOT];
};
Blockly.Python['lists_indexOf'] = function(block) {
// Find an item in the list.
- var argument0 = Blockly.Python.valueToCode(block, 'FIND',
+ var item = Blockly.Python.valueToCode(block, 'FIND',
Blockly.Python.ORDER_NONE) || '[]';
- var argument1 = Blockly.Python.valueToCode(block, 'VALUE',
- Blockly.Python.ORDER_MEMBER) || '\'\'';
- var code;
+ var list = Blockly.Python.valueToCode(block, 'VALUE',
+ Blockly.Python.ORDER_NONE) || '\'\'';
+ if (Blockly.Python.ONE_BASED_INDEXING) {
+ var errorIndex = ' 0';
+ var firstIndexAdjustment = ' + 1';
+ var lastIndexAdjustment = '';
+ } else {
+ var errorIndex = ' -1';
+ var firstIndexAdjustment = '';
+ var lastIndexAdjustment = ' - 1';
+ }
if (block.getFieldValue('END') == 'FIRST') {
var functionName = Blockly.Python.provideFunction_(
'first_index',
- ['def ' + Blockly.Python.FUNCTION_NAME_PLACEHOLDER_ + '(myList, elem):',
- ' try: theIndex = myList.index(elem) + 1',
- ' except: theIndex = 0',
- ' return theIndex']);
- code = functionName + '(' + argument1 + ', ' + argument0 + ')';
- return [code, Blockly.Python.ORDER_FUNCTION_CALL];
- } else {
- var functionName = Blockly.Python.provideFunction_(
- 'last_index',
- ['def ' + Blockly.Python.FUNCTION_NAME_PLACEHOLDER_ + '(myList, elem):',
- ' try: theIndex = len(myList) - myList[::-1].index(elem)',
- ' except: theIndex = 0',
- ' return theIndex']);
- code = functionName + '(' + argument1 + ', ' + argument0 + ')';
+ ['def ' + Blockly.Python.FUNCTION_NAME_PLACEHOLDER_ +
+ '(my_list, elem):',
+ ' try: index = my_list.index(elem)' + firstIndexAdjustment,
+ ' except: index =' + errorIndex,
+ ' return index']);
+ var code = functionName + '(' + list + ', ' + item + ')';
return [code, Blockly.Python.ORDER_FUNCTION_CALL];
}
+ var functionName = Blockly.Python.provideFunction_(
+ 'last_index',
+ ['def ' + Blockly.Python.FUNCTION_NAME_PLACEHOLDER_ + '(my_list, elem):',
+ ' try: index = len(my_list) - my_list[::-1].index(elem)' +
+ lastIndexAdjustment,
+ ' except: index =' + errorIndex,
+ ' return index']);
+ var code = functionName + '(' + list + ', ' + item + ')';
+ return [code, Blockly.Python.ORDER_FUNCTION_CALL];
};
Blockly.Python['lists_getIndex'] = function(block) {
@@ -103,85 +112,76 @@ Blockly.Python['lists_getIndex'] = function(block) {
// Note: Until January 2013 this block did not have MODE or WHERE inputs.
var mode = block.getFieldValue('MODE') || 'GET';
var where = block.getFieldValue('WHERE') || 'FROM_START';
- var at = Blockly.Python.valueToCode(block, 'AT',
- Blockly.Python.ORDER_UNARY_SIGN) || '1';
- var list = Blockly.Python.valueToCode(block, 'VALUE',
- Blockly.Python.ORDER_MEMBER) || '[]';
+ var listOrder = (where == 'RANDOM') ? Blockly.Python.ORDER_NONE :
+ Blockly.Python.ORDER_MEMBER;
+ var list = Blockly.Python.valueToCode(block, 'VALUE', listOrder) || '[]';
- if (where == 'FIRST') {
- if (mode == 'GET') {
- var code = list + '[0]';
- return [code, Blockly.Python.ORDER_MEMBER];
- } else {
- var code = list + '.pop(0)';
- if (mode == 'GET_REMOVE') {
+ switch (where) {
+ case 'FIRST':
+ if (mode == 'GET') {
+ var code = list + '[0]';
+ return [code, Blockly.Python.ORDER_MEMBER];
+ } else if (mode == 'GET_REMOVE') {
+ var code = list + '.pop(0)';
return [code, Blockly.Python.ORDER_FUNCTION_CALL];
} else if (mode == 'REMOVE') {
- return code + '\n';
+ return list + '.pop(0)\n';
}
- }
- } else if (where == 'LAST') {
- if (mode == 'GET') {
- var code = list + '[-1]';
- return [code, Blockly.Python.ORDER_MEMBER];
- } else {
- var code = list + '.pop()';
- if (mode == 'GET_REMOVE') {
+ break;
+ case 'LAST':
+ if (mode == 'GET') {
+ var code = list + '[-1]';
+ return [code, Blockly.Python.ORDER_MEMBER];
+ } else if (mode == 'GET_REMOVE') {
+ var code = list + '.pop()';
return [code, Blockly.Python.ORDER_FUNCTION_CALL];
} else if (mode == 'REMOVE') {
- return code + '\n';
+ return list + '.pop()\n';
}
- }
- } else if (where == 'FROM_START') {
- // Blockly uses one-based indicies.
- if (Blockly.isNumber(at)) {
- // If the index is a naked number, decrement it right now.
- at = parseInt(at, 10) - 1;
- } else {
- // If the index is dynamic, decrement it in code.
- at = 'int(' + at + ' - 1)';
- }
- if (mode == 'GET') {
- var code = list + '[' + at + ']';
- return [code, Blockly.Python.ORDER_MEMBER];
- } else {
- var code = list + '.pop(' + at + ')';
- if (mode == 'GET_REMOVE') {
+ break;
+ case 'FROM_START':
+ var at = Blockly.Python.getAdjustedInt(block, 'AT');
+ if (mode == 'GET') {
+ var code = list + '[' + at + ']';
+ return [code, Blockly.Python.ORDER_MEMBER];
+ } else if (mode == 'GET_REMOVE') {
+ var code = list + '.pop(' + at + ')';
return [code, Blockly.Python.ORDER_FUNCTION_CALL];
} else if (mode == 'REMOVE') {
- return code + '\n';
+ return list + '.pop(' + at + ')\n';
}
- }
- } else if (where == 'FROM_END') {
- if (mode == 'GET') {
- var code = list + '[-' + at + ']';
- return [code, Blockly.Python.ORDER_MEMBER];
- } else {
- var code = list + '.pop(-' + at + ')';
- if (mode == 'GET_REMOVE') {
+ break;
+ case'FROM_END':
+ var at = Blockly.Python.getAdjustedInt(block, 'AT', 1, true);
+ if (mode == 'GET') {
+ var code = list + '[' + at + ']';
+ return [code, Blockly.Python.ORDER_MEMBER];
+ } else if (mode == 'GET_REMOVE') {
+ var code = list + '.pop(' + at + ')';
return [code, Blockly.Python.ORDER_FUNCTION_CALL];
} else if (mode == 'REMOVE') {
- return code + '\n';
+ return list + '.pop(' + at + ')\n';
}
- }
- } else if (where == 'RANDOM') {
- Blockly.Python.definitions_['import_random'] = 'import random';
- if (mode == 'GET') {
- code = 'random.choice(' + list + ')';
- return [code, Blockly.Python.ORDER_FUNCTION_CALL];
- } else {
- var functionName = Blockly.Python.provideFunction_(
- 'lists_remove_random_item',
- ['def ' + Blockly.Python.FUNCTION_NAME_PLACEHOLDER_ + '(myList):',
- ' x = int(random.random() * len(myList))',
- ' return myList.pop(x)']);
- code = functionName + '(' + list + ')';
- if (mode == 'GET_REMOVE') {
+ break;
+ case 'RANDOM':
+ Blockly.Python.definitions_['import_random'] = 'import random';
+ if (mode == 'GET') {
+ code = 'random.choice(' + list + ')';
return [code, Blockly.Python.ORDER_FUNCTION_CALL];
- } else if (mode == 'REMOVE') {
- return code + '\n';
+ } else {
+ var functionName = Blockly.Python.provideFunction_(
+ 'lists_remove_random_item',
+ ['def ' + Blockly.Python.FUNCTION_NAME_PLACEHOLDER_ + '(myList):',
+ ' x = int(random.random() * len(myList))',
+ ' return myList.pop(x)']);
+ code = functionName + '(' + list + ')';
+ if (mode == 'GET_REMOVE') {
+ return [code, Blockly.Python.ORDER_FUNCTION_CALL];
+ } else if (mode == 'REMOVE') {
+ return code + '\n';
+ }
}
- }
+ break;
}
throw 'Unhandled combination (lists_getIndex).';
};
@@ -193,8 +193,6 @@ Blockly.Python['lists_setIndex'] = function(block) {
Blockly.Python.ORDER_MEMBER) || '[]';
var mode = block.getFieldValue('MODE') || 'GET';
var where = block.getFieldValue('WHERE') || 'FROM_START';
- var at = Blockly.Python.valueToCode(block, 'AT',
- Blockly.Python.ORDER_NONE) || '1';
var value = Blockly.Python.valueToCode(block, 'TO',
Blockly.Python.ORDER_NONE) || 'None';
// Cache non-trivial values to variables to prevent repeated look-ups.
@@ -209,51 +207,52 @@ Blockly.Python['lists_setIndex'] = function(block) {
list = listVar;
return code;
}
- if (where == 'FIRST') {
- if (mode == 'SET') {
- return list + '[0] = ' + value + '\n';
- } else if (mode == 'INSERT') {
- return list + '.insert(0, ' + value + ')\n';
- }
- } else if (where == 'LAST') {
- if (mode == 'SET') {
- return list + '[-1] = ' + value + '\n';
- } else if (mode == 'INSERT') {
- return list + '.append(' + value + ')\n';
- }
- } else if (where == 'FROM_START') {
- // Blockly uses one-based indicies.
- if (Blockly.isNumber(at)) {
- // If the index is a naked number, decrement it right now.
- at = parseInt(at, 10) - 1;
- } else {
- // If the index is dynamic, decrement it in code.
- at = 'int(' + at + ' - 1)';
- }
- if (mode == 'SET') {
- return list + '[' + at + '] = ' + value + '\n';
- } else if (mode == 'INSERT') {
- return list + '.insert(' + at + ', ' + value + ')\n';
- }
- } else if (where == 'FROM_END') {
- if (mode == 'SET') {
- return list + '[-' + at + '] = ' + value + '\n';
- } else if (mode == 'INSERT') {
- return list + '.insert(-' + at + ', ' + value + ')\n';
- }
- } else if (where == 'RANDOM') {
- Blockly.Python.definitions_['import_random'] = 'import random';
- var code = cacheList();
- var xVar = Blockly.Python.variableDB_.getDistinctName(
- 'tmp_x', Blockly.Variables.NAME_TYPE);
- code += xVar + ' = int(random.random() * len(' + list + '))\n';
- if (mode == 'SET') {
- code += list + '[' + xVar + '] = ' + value + '\n';
- return code;
- } else if (mode == 'INSERT') {
- code += list + '.insert(' + xVar + ', ' + value + ')\n';
- return code;
- }
+
+ switch (where) {
+ case 'FIRST':
+ if (mode == 'SET') {
+ return list + '[0] = ' + value + '\n';
+ } else if (mode == 'INSERT') {
+ return list + '.insert(0, ' + value + ')\n';
+ }
+ break;
+ case 'LAST':
+ if (mode == 'SET') {
+ return list + '[-1] = ' + value + '\n';
+ } else if (mode == 'INSERT') {
+ return list + '.append(' + value + ')\n';
+ }
+ break;
+ case 'FROM_START':
+ var at = Blockly.Python.getAdjustedInt(block, 'AT');
+ if (mode == 'SET') {
+ return list + '[' + at + '] = ' + value + '\n';
+ } else if (mode == 'INSERT') {
+ return list + '.insert(' + at + ', ' + value + ')\n';
+ }
+ break;
+ case 'FROM_END':
+ var at = Blockly.Python.getAdjustedInt(block, 'AT', 1, true);
+ if (mode == 'SET') {
+ return list + '[' + at + '] = ' + value + '\n';
+ } else if (mode == 'INSERT') {
+ return list + '.insert(' + at + ', ' + value + ')\n';
+ }
+ break;
+ case 'RANDOM':
+ Blockly.Python.definitions_['import_random'] = 'import random';
+ var code = cacheList();
+ var xVar = Blockly.Python.variableDB_.getDistinctName(
+ 'tmp_x', Blockly.Variables.NAME_TYPE);
+ code += xVar + ' = int(random.random() * len(' + list + '))\n';
+ if (mode == 'SET') {
+ code += list + '[' + xVar + '] = ' + value + '\n';
+ return code;
+ } else if (mode == 'INSERT') {
+ code += list + '.insert(' + xVar + ', ' + value + ')\n';
+ return code;
+ }
+ break;
}
throw 'Unhandled combination (lists_setIndex).';
};
@@ -264,49 +263,42 @@ Blockly.Python['lists_getSublist'] = function(block) {
Blockly.Python.ORDER_MEMBER) || '[]';
var where1 = block.getFieldValue('WHERE1');
var where2 = block.getFieldValue('WHERE2');
- var at1 = Blockly.Python.valueToCode(block, 'AT1',
- Blockly.Python.ORDER_ADDITIVE) || '1';
- var at2 = Blockly.Python.valueToCode(block, 'AT2',
- Blockly.Python.ORDER_ADDITIVE) || '1';
- if (where1 == 'FIRST' || (where1 == 'FROM_START' && at1 == '1')) {
- at1 = '';
- } else if (where1 == 'FROM_START') {
- // Blockly uses one-based indicies.
- if (Blockly.isNumber(at1)) {
- // If the index is a naked number, decrement it right now.
- at1 = parseInt(at1, 10) - 1;
- } else {
- // If the index is dynamic, decrement it in code.
- at1 = 'int(' + at1 + ' - 1)';
- }
- } else if (where1 == 'FROM_END') {
- if (Blockly.isNumber(at1)) {
- at1 = -parseInt(at1, 10);
- } else {
- at1 = '-int(' + at1 + ')';
- }
+ switch (where1) {
+ case 'FROM_START':
+ var at1 = Blockly.Python.getAdjustedInt(block, 'AT1');
+ if (at1 == '0') {
+ at1 = '';
+ }
+ break;
+ case 'FROM_END':
+ var at1 = Blockly.Python.getAdjustedInt(block, 'AT1', 1, true);
+ break;
+ case 'FIRST':
+ var at1 = '';
+ break;
+ default:
+ throw 'Unhandled option (lists_getSublist)';
}
- if (where2 == 'LAST' || (where2 == 'FROM_END' && at2 == '1')) {
- at2 = '';
- } else if (where1 == 'FROM_START') {
- if (Blockly.isNumber(at2)) {
- at2 = parseInt(at2, 10);
- } else {
- at2 = 'int(' + at2 + ')';
- }
- } else if (where1 == 'FROM_END') {
- if (Blockly.isNumber(at2)) {
- // If the index is a naked number, increment it right now.
- // Add special case for -0.
- at2 = 1 - parseInt(at2, 10);
- if (at2 == 0) {
+ switch (where2) {
+ case 'FROM_START':
+ var at2 = Blockly.Python.getAdjustedInt(block, 'AT2', 1);
+ break;
+ case 'FROM_END':
+ var at2 = Blockly.Python.getAdjustedInt(block, 'AT2', 0, true);
+ // Ensure that if the result calculated is 0 that sub-sequence will
+ // include all elements as expected.
+ if (!Blockly.isNumber(String(at2))) {
+ Blockly.Python.definitions_['import_sys'] = 'import sys';
+ at2 += ' or sys.maxsize';
+ } else if (at2 == '0') {
at2 = '';
}
- } else {
- // If the index is dynamic, increment it in code.
- Blockly.Python.definitions_['import_sys'] = 'import sys';
- at2 = 'int(1 - ' + at2 + ') or sys.maxsize';
- }
+ break;
+ case 'LAST':
+ var at2 = '';
+ break;
+ default:
+ throw 'Unhandled option (lists_getSublist)';
}
var code = list + '[' + at1 + ' : ' + at2 + ']';
return [code, Blockly.Python.ORDER_MEMBER];
@@ -314,30 +306,30 @@ Blockly.Python['lists_getSublist'] = function(block) {
Blockly.Python['lists_sort'] = function(block) {
// Block for sorting a list.
- var listCode = (Blockly.Python.valueToCode(block, 'LIST',
- Blockly.Python.ORDER_MEMBER) || '[]');
+ var list = (Blockly.Python.valueToCode(block, 'LIST',
+ Blockly.Python.ORDER_NONE) || '[]');
var type = block.getFieldValue('TYPE');
var reverse = block.getFieldValue('DIRECTION') === '1' ? 'False' : 'True';
var sortFunctionName = Blockly.Python.provideFunction_('lists_sort',
['def ' + Blockly.Python.FUNCTION_NAME_PLACEHOLDER_ +
- '(listv, type, reversev):',
- ' def tryfloat(s):',
+ '(my_list, type, reverse):',
+ ' def try_float(s):',
' try:',
' return float(s)',
' except:',
' return 0',
- ' keyFuncts = {',
- ' "NUMERIC": tryfloat,',
+ ' key_funcs = {',
+ ' "NUMERIC": try_float,',
' "TEXT": str,',
' "IGNORE_CASE": lambda s: str(s).lower()',
' }',
- ' keyv = keyFuncts[type]',
- ' tmp_list = list(listv)', // Clone the list.
- ' return sorted(tmp_list, key=keyv, reverse=reversev)'
+ ' key_func = key_funcs[type]',
+ ' list_cpy = list(my_list)', // Clone the list.
+ ' return sorted(list_cpy, key=key_func, reverse=reverse)'
]);
var code = sortFunctionName +
- '(' + listCode + ', "' + type + '", ' + reverse + ')';
+ '(' + list + ', "' + type + '", ' + reverse + ')';
return [code, Blockly.Python.ORDER_FUNCTION_CALL];
};
diff --git a/generators/python/procedures.js b/generators/python/procedures.js
index daa7386aa..b90f38d5b 100644
--- a/generators/python/procedures.js
+++ b/generators/python/procedures.js
@@ -65,8 +65,8 @@ Blockly.Python['procedures_defreturn'] = function(block) {
branch = Blockly.Python.PASS;
}
var args = [];
- for (var x = 0; x < block.arguments_.length; x++) {
- args[x] = Blockly.Python.variableDB_.getName(block.arguments_[x],
+ for (var i = 0; i < block.arguments_.length; i++) {
+ args[i] = Blockly.Python.variableDB_.getName(block.arguments_[i],
Blockly.Variables.NAME_TYPE);
}
var code = 'def ' + funcName + '(' + args.join(', ') + '):\n' +
@@ -87,8 +87,8 @@ Blockly.Python['procedures_callreturn'] = function(block) {
var funcName = Blockly.Python.variableDB_.getName(block.getFieldValue('NAME'),
Blockly.Procedures.NAME_TYPE);
var args = [];
- for (var x = 0; x < block.arguments_.length; x++) {
- args[x] = Blockly.Python.valueToCode(block, 'ARG' + x,
+ for (var i = 0; i < block.arguments_.length; i++) {
+ args[i] = Blockly.Python.valueToCode(block, 'ARG' + i,
Blockly.Python.ORDER_NONE) || 'None';
}
var code = funcName + '(' + args.join(', ') + ')';
@@ -100,8 +100,8 @@ Blockly.Python['procedures_callnoreturn'] = function(block) {
var funcName = Blockly.Python.variableDB_.getName(block.getFieldValue('NAME'),
Blockly.Procedures.NAME_TYPE);
var args = [];
- for (var x = 0; x < block.arguments_.length; x++) {
- args[x] = Blockly.Python.valueToCode(block, 'ARG' + x,
+ for (var i = 0; i < block.arguments_.length; i++) {
+ args[i] = Blockly.Python.valueToCode(block, 'ARG' + i,
Blockly.Python.ORDER_NONE) || 'None';
}
var code = funcName + '(' + args.join(', ') + ')\n';
diff --git a/generators/python/text.js b/generators/python/text.js
index 3ae0ffc8e..84e19872a 100644
--- a/generators/python/text.js
+++ b/generators/python/text.js
@@ -38,32 +38,35 @@ Blockly.Python['text'] = function(block) {
Blockly.Python['text_join'] = function(block) {
// Create a string made up of any number of elements of any type.
//Should we allow joining by '-' or ',' or any other characters?
- var code;
- if (block.itemCount_ == 0) {
- return ['\'\'', Blockly.Python.ORDER_ATOMIC];
- } else if (block.itemCount_ == 1) {
- var argument0 = Blockly.Python.valueToCode(block, 'ADD0',
- Blockly.Python.ORDER_NONE) || '\'\'';
- code = 'str(' + argument0 + ')';
- return [code, Blockly.Python.ORDER_FUNCTION_CALL];
- } else if (block.itemCount_ == 2) {
- var argument0 = Blockly.Python.valueToCode(block, 'ADD0',
- Blockly.Python.ORDER_NONE) || '\'\'';
- var argument1 = Blockly.Python.valueToCode(block, 'ADD1',
- Blockly.Python.ORDER_NONE) || '\'\'';
- var code = 'str(' + argument0 + ') + str(' + argument1 + ')';
- return [code, Blockly.Python.ORDER_UNARY_SIGN];
- } else {
- var code = [];
- for (var n = 0; n < block.itemCount_; n++) {
- code[n] = Blockly.Python.valueToCode(block, 'ADD' + n,
- Blockly.Python.ORDER_NONE) || '\'\'';
- }
- var tempVar = Blockly.Python.variableDB_.getDistinctName('temp_value',
- Blockly.Variables.NAME_TYPE);
- code = '\'\'.join([str(' + tempVar + ') for ' + tempVar + ' in [' +
- code.join(', ') + ']])';
- return [code, Blockly.Python.ORDER_FUNCTION_CALL];
+ switch (block.itemCount_) {
+ case 0:
+ return ['\'\'', Blockly.Python.ORDER_ATOMIC];
+ break;
+ case 1:
+ var element = Blockly.Python.valueToCode(block, 'ADD0',
+ Blockly.Python.ORDER_NONE) || '\'\'';
+ var code = 'str(' + element + ')';
+ return [code, Blockly.Python.ORDER_FUNCTION_CALL];
+ break;
+ case 2:
+ var element0 = Blockly.Python.valueToCode(block, 'ADD0',
+ Blockly.Python.ORDER_NONE) || '\'\'';
+ var element1 = Blockly.Python.valueToCode(block, 'ADD1',
+ Blockly.Python.ORDER_NONE) || '\'\'';
+ var code = 'str(' + element0 + ') + str(' + element1 + ')';
+ return [code, Blockly.Python.ORDER_ADDITIVE];
+ break;
+ default:
+ var elements = [];
+ for (var i = 0; i < block.itemCount_; i++) {
+ elements[i] = Blockly.Python.valueToCode(block, 'ADD' + i,
+ Blockly.Python.ORDER_NONE) || '\'\'';
+ }
+ var tempVar = Blockly.Python.variableDB_.getDistinctName('x',
+ Blockly.Variables.NAME_TYPE);
+ var code = '\'\'.join([str(' + tempVar + ') for ' + tempVar + ' in [' +
+ elements.join(', ') + ']])';
+ return [code, Blockly.Python.ORDER_FUNCTION_CALL];
}
};
@@ -71,23 +74,23 @@ Blockly.Python['text_append'] = function(block) {
// Append to a variable in place.
var varName = Blockly.Python.variableDB_.getName(block.getFieldValue('VAR'),
Blockly.Variables.NAME_TYPE);
- var argument0 = Blockly.Python.valueToCode(block, 'TEXT',
+ var value = Blockly.Python.valueToCode(block, 'TEXT',
Blockly.Python.ORDER_NONE) || '\'\'';
- return varName + ' = str(' + varName + ') + str(' + argument0 + ')\n';
+ return varName + ' = str(' + varName + ') + str(' + value + ')\n';
};
Blockly.Python['text_length'] = function(block) {
// Is the string null or array empty?
- var argument0 = Blockly.Python.valueToCode(block, 'VALUE',
+ var text = Blockly.Python.valueToCode(block, 'VALUE',
Blockly.Python.ORDER_NONE) || '\'\'';
- return ['len(' + argument0 + ')', Blockly.Python.ORDER_FUNCTION_CALL];
+ return ['len(' + text + ')', Blockly.Python.ORDER_FUNCTION_CALL];
};
Blockly.Python['text_isEmpty'] = function(block) {
// Is the string null or array empty?
- var argument0 = Blockly.Python.valueToCode(block, 'VALUE',
+ var text = Blockly.Python.valueToCode(block, 'VALUE',
Blockly.Python.ORDER_NONE) || '\'\'';
- var code = 'not len(' + argument0 + ')';
+ var code = 'not len(' + text + ')';
return [code, Blockly.Python.ORDER_LOGICAL_NOT];
};
@@ -95,20 +98,21 @@ Blockly.Python['text_indexOf'] = function(block) {
// Search the text for a substring.
// Should we allow for non-case sensitive???
var operator = block.getFieldValue('END') == 'FIRST' ? 'find' : 'rfind';
- var argument0 = Blockly.Python.valueToCode(block, 'FIND',
+ var substring = Blockly.Python.valueToCode(block, 'FIND',
Blockly.Python.ORDER_NONE) || '\'\'';
- var argument1 = Blockly.Python.valueToCode(block, 'VALUE',
+ var text = Blockly.Python.valueToCode(block, 'VALUE',
Blockly.Python.ORDER_MEMBER) || '\'\'';
- var code = argument1 + '.' + operator + '(' + argument0 + ') + 1';
- return [code, Blockly.Python.ORDER_ADDITIVE];
+ var code = text + '.' + operator + '(' + substring + ')';
+ if (Blockly.Python.ONE_BASED_INDEXING) {
+ return [code + ' + 1', Blockly.Python.ORDER_ADDITIVE];
+ }
+ return [code, Blockly.Python.ORDER_FUNCTION_CALL];
};
Blockly.Python['text_charAt'] = function(block) {
// Get letter at index.
// Note: Until January 2013 this block did not have the WHERE input.
var where = block.getFieldValue('WHERE') || 'FROM_START';
- var at = Blockly.Python.valueToCode(block, 'AT',
- Blockly.Python.ORDER_UNARY_SIGN) || '1';
var text = Blockly.Python.valueToCode(block, 'VALUE',
Blockly.Python.ORDER_MEMBER) || '\'\'';
switch (where) {
@@ -119,18 +123,12 @@ Blockly.Python['text_charAt'] = function(block) {
var code = text + '[-1]';
return [code, Blockly.Python.ORDER_MEMBER];
case 'FROM_START':
- // Blockly uses one-based indicies.
- if (Blockly.isNumber(at)) {
- // If the index is a naked number, decrement it right now.
- at = parseInt(at, 10) - 1;
- } else {
- // If the index is dynamic, decrement it in code.
- at = 'int(' + at + ' - 1)';
- }
+ var at = Blockly.Python.getAdjustedInt(block, 'AT');
var code = text + '[' + at + ']';
return [code, Blockly.Python.ORDER_MEMBER];
case 'FROM_END':
- var code = text + '[-' + at + ']';
+ var at = Blockly.Python.getAdjustedInt(block, 'AT', 1, true);
+ var code = text + '[' + at + ']';
return [code, Blockly.Python.ORDER_MEMBER];
case 'RANDOM':
Blockly.Python.definitions_['import_random'] = 'import random';
@@ -147,53 +145,46 @@ Blockly.Python['text_charAt'] = function(block) {
Blockly.Python['text_getSubstring'] = function(block) {
// Get substring.
- var text = Blockly.Python.valueToCode(block, 'STRING',
- Blockly.Python.ORDER_MEMBER) || '\'\'';
var where1 = block.getFieldValue('WHERE1');
var where2 = block.getFieldValue('WHERE2');
- var at1 = Blockly.Python.valueToCode(block, 'AT1',
- Blockly.Python.ORDER_ADDITIVE) || '1';
- var at2 = Blockly.Python.valueToCode(block, 'AT2',
- Blockly.Python.ORDER_ADDITIVE) || '1';
- if (where1 == 'FIRST' || (where1 == 'FROM_START' && at1 == '1')) {
- at1 = '';
- } else if (where1 == 'FROM_START') {
- // Blockly uses one-based indicies.
- if (Blockly.isNumber(at1)) {
- // If the index is a naked number, decrement it right now.
- at1 = parseInt(at1, 10) - 1;
- } else {
- // If the index is dynamic, decrement it in code.
- at1 = 'int(' + at1 + ' - 1)';
- }
- } else if (where1 == 'FROM_END') {
- if (Blockly.isNumber(at1)) {
- at1 = -parseInt(at1, 10);
- } else {
- at1 = '-int(' + at1 + ')';
- }
+ var text = Blockly.Python.valueToCode(block, 'STRING',
+ Blockly.Python.ORDER_MEMBER) || '\'\'';
+ switch (where1) {
+ case 'FROM_START':
+ var at1 = Blockly.Python.getAdjustedInt(block, 'AT1');
+ if (at1 == '0') {
+ at1 = '';
+ }
+ break;
+ case 'FROM_END':
+ var at1 = Blockly.Python.getAdjustedInt(block, 'AT1', 1, true);
+ break;
+ case 'FIRST':
+ var at1 = '';
+ break;
+ default:
+ throw 'Unhandled option (text_getSubstring)';
}
- if (where2 == 'LAST' || (where2 == 'FROM_END' && at2 == '1')) {
- at2 = '';
- } else if (where1 == 'FROM_START') {
- if (Blockly.isNumber(at2)) {
- at2 = parseInt(at2, 10);
- } else {
- at2 = 'int(' + at2 + ')';
- }
- } else if (where1 == 'FROM_END') {
- if (Blockly.isNumber(at2)) {
- // If the index is a naked number, increment it right now.
- at2 = 1 - parseInt(at2, 10);
- if (at2 == 0) {
+ switch (where2) {
+ case 'FROM_START':
+ var at2 = Blockly.Python.getAdjustedInt(block, 'AT2', 1);
+ break;
+ case 'FROM_END':
+ var at2 = Blockly.Python.getAdjustedInt(block, 'AT2', 0, true);
+ // Ensure that if the result calculated is 0 that sub-sequence will
+ // include all elements as expected.
+ if (!Blockly.isNumber(String(at2))) {
+ Blockly.Python.definitions_['import_sys'] = 'import sys';
+ at2 += ' or sys.maxsize';
+ } else if (at2 == '0') {
at2 = '';
}
- } else {
- // If the index is dynamic, increment it in code.
- // Add special case for -0.
- Blockly.Python.definitions_['import_sys'] = 'import sys';
- at2 = 'int(1 - ' + at2 + ') or sys.maxsize';
- }
+ break;
+ case 'LAST':
+ var at2 = '';
+ break;
+ default:
+ throw 'Unhandled option (text_getSubstring)';
}
var code = text + '[' + at1 + ' : ' + at2 + ']';
return [code, Blockly.Python.ORDER_MEMBER];
@@ -207,10 +198,10 @@ Blockly.Python['text_changeCase'] = function(block) {
'TITLECASE': '.title()'
};
var operator = OPERATORS[block.getFieldValue('CASE')];
- var argument0 = Blockly.Python.valueToCode(block, 'TEXT',
+ var text = Blockly.Python.valueToCode(block, 'TEXT',
Blockly.Python.ORDER_MEMBER) || '\'\'';
- var code = argument0 + operator;
- return [code, Blockly.Python.ORDER_MEMBER];
+ var code = text + operator;
+ return [code, Blockly.Python.ORDER_FUNCTION_CALL];
};
Blockly.Python['text_trim'] = function(block) {
@@ -221,17 +212,17 @@ Blockly.Python['text_trim'] = function(block) {
'BOTH': '.strip()'
};
var operator = OPERATORS[block.getFieldValue('MODE')];
- var argument0 = Blockly.Python.valueToCode(block, 'TEXT',
+ var text = Blockly.Python.valueToCode(block, 'TEXT',
Blockly.Python.ORDER_MEMBER) || '\'\'';
- var code = argument0 + operator;
- return [code, Blockly.Python.ORDER_MEMBER];
+ var code = text + operator;
+ return [code, Blockly.Python.ORDER_FUNCTION_CALL];
};
Blockly.Python['text_print'] = function(block) {
// Print statement.
- var argument0 = Blockly.Python.valueToCode(block, 'TEXT',
+ var msg = Blockly.Python.valueToCode(block, 'TEXT',
Blockly.Python.ORDER_NONE) || '\'\'';
- return 'print(' + argument0 + ')\n';
+ return 'print(' + msg + ')\n';
};
Blockly.Python['text_prompt_ext'] = function(block) {
diff --git a/tests/generators/colour.xml b/tests/generators/colour.xml
index 78ac58516..bae853d4d 100644
--- a/tests/generators/colour.xml
+++ b/tests/generators/colour.xml
@@ -3,7 +3,11 @@
test colour picker
- static colour
+
+
+ static colour
+
+
#ff6600
@@ -21,7 +25,11 @@
test rgb
- from rgb
+
+
+ from rgb
+
+
@@ -88,7 +96,11 @@
- test name
+
+
+ test name
+
+
@@ -105,7 +117,11 @@
- test name
+
+
+ test name
+
+
@@ -137,7 +153,11 @@
- test name
+
+
+ test name
+
+
TRUE
@@ -192,7 +212,11 @@
test blend
- blend
+
+
+ blend
+
+
diff --git a/tests/generators/functions.xml b/tests/generators/functions.xml
index ce450b11a..b189ed355 100644
--- a/tests/generators/functions.xml
+++ b/tests/generators/functions.xml
@@ -8,7 +8,11 @@
- test recurse
+
+
+ test recurse
+
+
@@ -53,7 +57,11 @@
- procedure with global
+
+
+ procedure with global
+
+
proc z
@@ -84,7 +92,11 @@
- procedure no return
+
+
+ procedure no return
+
+
TRUE
@@ -111,7 +123,11 @@
- procedure return
+
+
+ procedure return
+
+
FALSE
@@ -192,7 +208,11 @@
test function
- function with arguments
+
+
+ function with arguments
+
+
@@ -218,7 +238,11 @@
- function with side effect
+
+
+ function with side effect
+
+
func z
@@ -247,7 +271,11 @@
- function with global
+
+
+ function with global
+
+
@@ -267,7 +295,11 @@
- function with scope
+
+
+ function with scope
+
+
func a
@@ -280,7 +312,11 @@
- function return
+
+
+ function return
+
+
TRUE
@@ -296,7 +332,11 @@
- function no return
+
+
+ function no return
+
+
FALSE
diff --git a/tests/generators/index.html b/tests/generators/index.html
index 5ae75e553..a5003ca51 100644
--- a/tests/generators/index.html
+++ b/tests/generators/index.html
@@ -153,17 +153,23 @@ function toXml() {
}
function toJavaScript() {
+ var oneBasedIndexing = document.getElementById('indexing').checked;
+ Blockly.JavaScript.ONE_BASED_INDEXING = oneBasedIndexing;
var code = '\'use strict\';\n\n'
code += Blockly.JavaScript.workspaceToCode(workspace);
setOutput(code);
}
function toPython() {
+ var oneBasedIndexing = document.getElementById('indexing').checked;
+ Blockly.Python.ONE_BASED_INDEXING = oneBasedIndexing;
var code = Blockly.Python.workspaceToCode(workspace);
setOutput(code);
}
function toPhp() {
+ var oneBasedIndexing = document.getElementById('indexing').checked;
+ Blockly.PHP.ONE_BASED_INDEXING = oneBasedIndexing;
var code = Blockly.PHP.workspaceToCode(workspace);
setOutput(code);
}
@@ -174,6 +180,8 @@ function toLua() {
}
function toDart() {
+ var oneBasedIndexing = document.getElementById('indexing').checked;
+ Blockly.Dart.ONE_BASED_INDEXING = oneBasedIndexing;
var code = Blockly.Dart.workspaceToCode(workspace);
setOutput(code);
}
@@ -212,9 +220,22 @@ h1 {
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -305,6 +326,10 @@ h1 {
+
+ Generate with one-based indexing
+
+
Generate:
diff --git a/tests/generators/lists.xml b/tests/generators/lists.xml
index d803a14ad..88e4946b5 100644
--- a/tests/generators/lists.xml
+++ b/tests/generators/lists.xml
@@ -1,934 +1,65 @@
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- test create
- Describe this function...
-
-
- test create empty
-
-
-
-
-
-
-
-
-
-
- test create items
-
-
-
-
-
- TRUE
-
-
-
-
- love
-
-
-
-
-
-
-
-
-
- TRUE
-
-
-
-
- love
-
-
-
-
-
-
- test create repeated
-
-
-
-
- Eject
-
-
-
-
- 3
-
-
-
-
-
-
-
-
-
- Eject
-
-
-
-
- Eject
-
-
-
-
- Eject
-
-
-
-
-
-
-
-
-
-
-
-
- test empty
- Describe this function...
-
-
- not empty
- FALSE
-
-
-
-
-
-
-
- 0
-
-
-
-
-
-
-
-
- empty
- TRUE
-
-
-
-
-
-
-
-
-
-
-
-
-
- test length
- Describe this function...
-
-
- zero length
-
-
-
-
-
-
-
-
-
- 0
-
-
-
-
- one length
-
-
-
-
-
-
-
- cat
-
-
-
-
-
-
-
-
- 1
-
-
-
-
- three length
-
-
-
-
-
-
-
- cat
-
-
-
-
- TRUE
-
-
-
-
-
-
-
-
-
-
-
- 3
-
-
-
-
-
-
-
-
-
-
- test find
- Describe this function...
-
-
- find first
-
-
- FIRST
-
-
-
-
-
- Alice
-
-
-
-
- Eve
-
-
-
-
- Bob
-
-
-
-
- Eve
-
-
-
-
-
-
- Eve
-
-
-
-
-
-
- 2
-
-
-
-
- find last
-
-
- LAST
-
-
-
-
-
- Alice
-
-
-
-
- Eve
-
-
-
-
- Bob
-
-
-
-
- Eve
-
-
-
-
-
-
- Eve
-
-
-
-
-
-
- 4
-
-
-
-
- find none
-
-
- FIRST
-
-
-
-
-
- Alice
-
-
-
-
- Bob
-
-
-
-
- Carol
-
-
-
-
- Dave
-
-
-
-
-
-
- Eve
-
-
-
-
-
-
- 0
-
-
-
-
-
-
-
-
-
-
- test get
- Describe this function...
-
-
- list
-
-
-
-
-
- Kirk
-
-
-
-
- Spock
-
-
-
-
- McCoy
-
-
-
-
-
-
- get first
-
-
-
- GET
- FIRST
-
-
- list
-
-
-
-
-
-
- Kirk
-
-
-
-
- get last
-
-
-
- GET
- LAST
-
-
- list
-
-
-
-
-
-
- McCoy
-
-
-
-
- get random
- TRUE
-
-
-
- POSITIVE
-
-
- FIRST
-
-
- list
-
-
-
-
-
- GET
- RANDOM
-
-
- list
-
-
-
-
-
-
-
-
-
-
- get #
-
-
-
- GET
- FROM_START
-
-
- list
-
-
-
-
- 2
-
-
-
-
-
-
- Spock
-
-
-
-
- get #-end
-
-
-
- GET
- FROM_END
-
-
- list
-
-
-
-
- 3
-
-
-
-
-
-
- Kirk
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- test get remove
- Describe this function...
-
-
- list
-
-
-
-
-
- Kirk
-
-
-
-
- Spock
-
-
-
-
- McCoy
-
-
-
-
-
-
- getremove first
-
-
-
- GET_REMOVE
- FIRST
-
-
- list
-
-
-
-
-
-
- Kirk
-
-
-
-
- getremove first list
-
-
- list
-
-
-
-
-
-
-
- Spock
-
-
-
-
- McCoy
-
-
-
-
-
-
- list
-
-
-
-
-
- Kirk
-
-
-
-
- Spock
-
-
-
-
- McCoy
-
-
-
-
-
-
- getremove last
-
-
-
- GET_REMOVE
- LAST
-
-
- list
-
-
-
-
-
-
- McCoy
-
-
-
-
- getremove last list
-
-
- list
-
-
-
-
-
-
-
- Kirk
-
-
-
-
- Spock
-
-
-
-
-
-
- list
-
-
-
-
-
- Kirk
-
-
-
-
- Spock
-
-
-
-
- McCoy
-
-
-
-
-
-
- getremove random
- TRUE
-
-
- EQ
-
-
- FIRST
-
-
- list
-
-
-
-
-
- GET_REMOVE
- RANDOM
-
-
- list
-
-
-
-
-
-
-
-
- 0
-
-
-
-
-
-
- getremove random list
-
-
-
-
- list
-
-
-
-
-
-
- 2
-
-
-
-
- list
-
-
-
-
-
- Kirk
-
-
-
-
- Spock
-
-
-
-
- McCoy
-
-
-
-
-
-
- getremove #
-
-
-
- GET_REMOVE
- FROM_START
-
-
- list
-
-
-
-
- 2
-
-
-
-
-
-
- Spock
-
-
-
-
- getremove # list
-
-
- list
-
-
-
-
-
-
-
- Kirk
-
-
-
-
- McCoy
-
-
-
-
-
-
- list
-
-
-
-
-
- Kirk
-
-
-
-
- Spock
-
-
-
-
- McCoy
-
-
-
-
-
-
- getremove #-end
-
-
-
- GET_REMOVE
- FROM_END
-
-
- list
-
-
-
-
- 3
-
-
-
-
-
-
- Kirk
-
-
+
-
- getremove #-end list
-
-
- list
-
-
-
-
-
-
-
- Spock
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
- McCoy
-
-
+
-
+
@@ -960,14 +91,2926 @@
-
- test remove
- Describe this function...
+
+
+
+
+ check number of calls
+ Checks that the number of calls is one in order to confirm that a function was only called once.
+
+
+ test name
+
+
+ number of calls
+
+
+
+
+
+
+ test name
+
+
+
+
+ number of calls
+
+
+
+
+ 1
+
+
+
+
+
+
+
+
+ test create
+ Tests the "create list with" and "create empty list" blocks.
+
+
+
+
+ create empty
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ create items
+
+
+
+
+
+
+
+ TRUE
+
+
+
+
+ love
+
+
+
+
+
+
+
+
+
+ TRUE
+
+
+
+
+ love
+
+
+
+
+
+
+
+
+ create repeated
+
+
+
+
+
+
+ Eject
+
+
+
+
+ 3
+
+
+
+
+
+
+
+
+
+ Eject
+
+
+
+
+ Eject
+
+
+
+
+ Eject
+
+
+
+
+
+
+
+
+ create repeated order
+
+
+
+
+
+
+ Eject
+
+
+
+
+ ADD
+
+
+ 0
+
+
+
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+ Eject
+
+
+
+
+ Eject
+
+
+
+
+ Eject
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ get empty list
+ Creates an empty list for use with the empty test.
+
+
+
+
+
+ test empty
+ Tests the "is empty" block.
+
+
+ FALSE
+
+
+ not empty
+
+
+
+
+
+
+
+
+
+ 0
+
+
+
+
+
+
+
+
+ TRUE
+
+
+ empty
+
+
+
+
+
+
+
+
+
+
+
+ TRUE
+
+
+ empty complex
+
+
+
+
+
+
+
+
+
+
+
+
+
+ TRUE
+
+
+ empty order
+
+
+
+
+
+
+
+
+ TRUE
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ test length
+ Tests the "length" block.
+
+
+
+
+ zero length
+
+
+
+
+
+
+
+
+
+
+
+ 0
+
+
+
+
+
+
+ one length
+
+
+
+
+
+
+
+
+
+ cat
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+
+
+ three length
+
+
+
+
+
+
+
+
+
+ cat
+
+
+
+
+ TRUE
+
+
+
+
+
+
+
+
+
+
+
+ 3
+
+
+
+
+
+
+ two length order
+
+
+
+
+
+
+
+
+ TRUE
+
+
+
+
+
+
+
+ cat
+
+
+
+
+ TRUE
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 2
+
+
+
+
+
+
+
+
+
+
+
+
+ test find simple
+ Tests the "find" block with a variable.
+
+
+ list
+
+
+
+
+
+ Alice
+
+
+
+
+ Eve
+
+
+
+
+ Bob
+
+
+
+
+ Eve
+
+
+
+
+
+
+
+
+ find first simple
+
+
+
+
+ FIRST
+
+
+ list
+
+
+
+
+ Eve
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+
+
+
+
+ find last simple
+
+
+
+
+ LAST
+
+
+ list
+
+
+
+
+ Eve
+
+
+
+
+
+
+
+
+ 3
+
+
+
+
+
+
+
+
+ find none simple
+
+
+
+
+ FIRST
+
+
+ list
+
+
+
+
+ Dave
+
+
+
+
+
+
+
+
+ -1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ get names
+ Creates a list for use with the find test.
+
+
+ number of calls
+
+
+ 1
+
+
+
+
+
+
+
+
+
+ Alice
+
+
+
+
+ Eve
+
+
+
+
+ Bob
+
+
+
+
+ Eve
+
+
+
+
+
+
+ test find complex
+ Tests the "find" block with a function call.
+
+
+ number of calls
+
+
+ 0
+
+
+
+
+
+
+ find first complex
+
+
+
+
+ FIRST
+
+
+
+
+
+
+
+ Eve
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+
+
+
+
+
+
+
+ find first complex
+
+
+
+
+ number of calls
+
+
+ 0
+
+
+
+
+
+
+ find first order complex
+
+
+
+
+ FIRST
+
+
+
+
+ TRUE
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Eve
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+
+
+
+
+
+
+
+ find first order complex
+
+
+
+
+ number of calls
+
+
+ 0
+
+
+
+
+
+
+ find last complex
+
+
+
+
+ LAST
+
+
+
+
+
+
+
+ Eve
+
+
+
+
+
+
+
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+ find last complex
+
+
+
+
+ number of calls
+
+
+ 0
+
+
+
+
+
+
+ find last order complex
+
+
+
+
+ LAST
+
+
+
+
+ TRUE
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Eve
+
+
+
+
+
+
+
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+ find last order complex
+
+
+
+
+ number of calls
+
+
+ 0
+
+
+
+
+
+
+ find none complex
+
+
+
+
+ FIRST
+
+
+
+
+
+
+
+ Dave
+
+
+
+
+
+
+
+
+ -1
+
+
+
+
+
+
+
+
+
+
+
+ find none complex
+
+
+
+
+ number of calls
+
+
+ 0
+
+
+
+
+
+
+ find none order complex
+
+
+
+
+ FIRST
+
+
+
+
+ TRUE
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Dave
+
+
+
+
+
+
+
+
+ -1
+
+
+
+
+
+
+
+
+
+
+
+ find none order complex
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ test get simple
+ Tests the "get" block with a variable.
list
-
+
+
+
+
+ Kirk
+
+
+
+
+ Spock
+
+
+
+
+ McCoy
+
+
+
+
+
+
+
+
+ get first simple
+
+
+
+
+
+ GET
+ FIRST
+
+
+ list
+
+
+
+
+
+
+ Kirk
+
+
+
+
+
+
+ get last simple
+
+
+
+
+
+ GET
+ LAST
+
+
+ list
+
+
+
+
+
+
+ McCoy
+
+
+
+
+ TRUE
+
+
+ get random simple
+
+
+
+
+ GT
+
+
+ FIRST
+
+
+ list
+
+
+
+
+
+ GET
+ RANDOM
+
+
+ list
+
+
+
+
+
+
+
+
+
+
+ -1
+
+
+
+
+
+
+
+
+
+
+ get # simple
+
+
+
+
+
+ GET
+ FROM_START
+
+
+ list
+
+
+
+
+
+
+ 1
+
+
+
+
+
+
+
+
+ Spock
+
+
+
+
+
+
+ get # order simple
+
+
+
+
+
+ GET
+ FROM_START
+
+
+ list
+
+
+
+
+
+
+ TRUE
+
+
+
+
+
+
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Spock
+
+
+
+
+
+
+ get #-end simple
+
+
+
+
+
+ GET
+ FROM_END
+
+
+ list
+
+
+
+
+
+
+ 2
+
+
+
+
+
+
+
+
+ Kirk
+
+
+
+
+
+
+ get #-end order simple
+
+
+
+
+
+ GET
+ FROM_END
+ The order for index for #-end is addition because this will catch errors in generators where most perform the operation ... - index.
+
+
+ list
+
+
+
+
+ ADD
+
+
+ 0
+
+
+
+
+
+
+ 2
+
+
+
+
+
+
+
+
+
+
+ Kirk
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ get star wars
+ Creates a list for use with the get test.
+
+
+ number of calls
+
+
+ 1
+
+
+
+
+
+
+
+
+
+ Kirk
+
+
+
+
+ Spock
+
+
+
+
+ McCoy
+
+
+
+
+
+
+ test get complex
+ Tests the "get" block with a function call.
+
+
+ list
+
+
+
+
+
+ Kirk
+
+
+
+
+ Spock
+
+
+
+
+ McCoy
+
+
+
+
+
+
+ number of calls
+
+
+ 0
+
+
+
+
+
+
+ get first complex
+
+
+
+
+
+ GET
+ FIRST
+
+
+
+
+
+
+
+
+
+ Kirk
+
+
+
+
+
+
+
+
+
+ get first complex
+
+
+
+
+ number of calls
+
+
+ 0
+
+
+
+
+
+
+ get first order complex
+
+
+
+
+
+ GET
+ FIRST
+
+
+
+
+ TRUE
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Kirk
+
+
+
+
+
+
+
+
+
+ get first order complex
+
+
+
+
+ number of calls
+
+
+ 0
+
+
+
+
+
+
+ get last complex
+
+
+
+
+
+ GET
+ LAST
+
+
+
+
+
+
+
+
+
+ McCoy
+
+
+
+
+
+
+
+
+
+ get last complex
+
+
+
+
+ number of calls
+
+
+ 0
+
+
+
+
+
+
+ get last order complex
+
+
+
+
+
+ GET
+ LAST
+
+
+
+
+ TRUE
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ McCoy
+
+
+
+
+
+
+
+
+
+ get last order complex
+
+
+
+
+ number of calls
+
+
+ 0
+
+
+
+
+ TRUE
+
+
+ get random complex
+
+
+
+
+ GT
+
+
+ FIRST
+
+
+ list
+
+
+
+
+
+ GET
+ RANDOM
+
+
+
+
+
+
+
+
+
+
+
+
+
+ -1
+
+
+
+
+
+
+
+
+
+
+
+
+
+ get random complex
+
+
+
+
+ number of calls
+
+
+ 0
+
+
+
+
+ TRUE
+
+
+ get random order complex
+
+
+
+
+ GT
+
+
+ FIRST
+
+
+ list
+
+
+
+
+
+ GET
+ RANDOM
+
+
+
+
+ TRUE
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ -1
+
+
+
+
+
+
+
+
+
+
+
+
+
+ get random order complex
+
+
+
+
+ number of calls
+
+
+ 0
+
+
+
+
+
+
+ get # complex
+
+
+
+
+
+ GET
+ FROM_START
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+
+
+
+
+ Spock
+
+
+
+
+
+
+
+
+
+ get # complex
+
+
+
+
+ number of calls
+
+
+ 0
+
+
+
+
+
+
+ get # order complex
+
+
+
+
+
+ GET
+ FROM_START
+
+
+
+
+ TRUE
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ TRUE
+
+
+
+
+
+
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Spock
+
+
+
+
+
+
+
+
+
+ get # order complex
+
+
+
+
+ number of calls
+
+
+ 0
+
+
+
+
+
+
+ get #-end complex
+
+
+
+
+
+ GET
+ FROM_END
+
+
+
+
+
+
+
+
+
+ 2
+
+
+
+
+
+
+
+
+ Kirk
+
+
+
+
+
+
+
+
+
+ get #-end complex
+
+
+
+
+ number of calls
+
+
+ 0
+
+
+
+
+
+
+ get #-end order complex
+
+
+
+
+
+ GET
+ FROM_END
+ The order for index for #-end is addition because this will catch errors in generators where most perform the operation ... - index.
+
+
+
+
+ TRUE
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ADD
+
+
+ 0
+
+
+
+
+
+
+ 2
+
+
+
+
+
+
+
+
+
+
+ Kirk
+
+
+
+
+
+
+
+
+
+ get #-end order complex
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ test getRemove
+ Tests the "get and remove" block.
+
+
+ list
+
+
+
+
+
+ Kirk
+
+
+
+
+ Spock
+
+
+
+
+ McCoy
+
+
+
+
+
+
+
+
+ getremove first
+
+
+
+
+
+ GET_REMOVE
+ FIRST
+
+
+ list
+
+
+
+
+
+
+ Kirk
+
+
+
+
+
+
+ getremove first list
+
+
+
+
+ list
+
+
+
+
+
+
+
+ Spock
+
+
+
+
+ McCoy
+
+
+
+
+
+
+ list
+
+
+
+
+
+ Kirk
+
+
+
+
+ Spock
+
+
+
+
+ McCoy
+
+
+
+
+
+
+
+
+ getremove first order
+
+
+
+
+
+ GET_REMOVE
+ FIRST
+
+
+
+
+ TRUE
+
+
+
+
+ list
+
+
+
+
+
+
+
+
+
+
+
+ Kirk
+
+
+
+
+
+
+ getremove first order list
+
+
+
+
+ list
+
+
+
+
+
+
+
+ Spock
+
+
+
+
+ McCoy
+
+
+
+
+
+
+ list
+
+
+
+
+
+ Kirk
+
+
+
+
+ Spock
+
+
+
+
+ McCoy
+
+
+
+
+
+
+
+
+ getremove last
+
+
+
+
+
+ GET_REMOVE
+ LAST
+
+
+ list
+
+
+
+
+
+
+ McCoy
+
+
+
+
+
+
+ getremove last list
+
+
+
+
+ list
+
+
+
+
+
+
+
+ Kirk
+
+
+
+
+ Spock
+
+
+
+
+
+
+ list
+
+
+
+
+
+ Kirk
+
+
+
+
+ Spock
+
+
+
+
+ McCoy
+
+
+
+
+
+
+
+
+ getremove last order
+
+
+
+
+
+ GET_REMOVE
+ LAST
+
+
+
+
+ TRUE
+
+
+
+
+ list
+
+
+
+
+
+
+
+
+
+
+
+ McCoy
+
+
+
+
+
+
+ getremove last order list
+
+
+
+
+ list
+
+
+
+
+
+
+
+ Kirk
+
+
+
+
+ Spock
+
+
+
+
+
+
+ list
+
+
+
+
+
+ Kirk
+
+
+
+
+ Spock
+
+
+
+
+ McCoy
+
+
+
+
+
+
+ TRUE
+
+
+ getremove random
+
+
+
+
+ EQ
+
+
+ FIRST
+
+
+ list
+
+
+
+
+
+ GET_REMOVE
+ RANDOM
+
+
+ list
+
+
+
+
+
+
+
+
+
+
+ -1
+
+
+
+
+
+
+
+
+
+
+ getremove random list
+
+
+
+
+
+
+ list
+
+
+
+
+
+
+ 2
+
+
+
+
+ list
+
+
+
+
+
+ Kirk
+
+
+
+
+ Spock
+
+
+
+
+ McCoy
+
+
+
+
+
+
+ TRUE
+
+
+ getremove random order
+
+
+
+
+ EQ
+
+
+ FIRST
+
+
+ list
+
+
+
+
+
+ GET_REMOVE
+ RANDOM
+
+
+
+
+ TRUE
+
+
+
+
+ list
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ -1
+
+
+
+
+
+
+
+
+
+
+ getremove random order list
+
+
+
+
+
+
+ list
+
+
+
+
+
+
+ 2
+
+
+
+
+ list
+
+
+
+
+
+ Kirk
+
+
+
+
+ Spock
+
+
+
+
+ McCoy
+
+
+
+
+
+
+
+
+ getremove #
+
+
+
+
+
+ GET_REMOVE
+ FROM_START
+
+
+ list
+
+
+
+
+
+
+ 1
+
+
+
+
+
+
+
+
+ Spock
+
+
+
+
+
+
+ getremove # list
+
+
+
+
+ list
+
+
+
+
+
+
+
+ Kirk
+
+
+
+
+ McCoy
+
+
+
+
+
+
+ list
+
+
+
+
+
+ Kirk
+
+
+
+
+ Spock
+
+
+
+
+ McCoy
+
+
+
+
+
+
+
+
+ getremove # order
+
+
+
+
+
+ GET_REMOVE
+ FROM_START
+
+
+
+
+ TRUE
+
+
+
+
+ list
+
+
+
+
+
+
+
+
+
+
+
+ TRUE
+
+
+
+
+
+
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Spock
+
+
+
+
+
+
+ getremove # order list
+
+
+
+
+ list
+
+
+
+
+
+
+
+ Kirk
+
+
+
+
+ McCoy
+
+
+
+
+
+
+ list
+
+
+
+
+
+ Kirk
+
+
+
+
+ Spock
+
+
+
+
+ McCoy
+
+
+
+
+
+
+
+
+ getremove #-end
+
+
+
+
+
+ GET_REMOVE
+ FROM_END
+
+
+ list
+
+
+
+
+
+
+ 2
+
+
+
+
+
+
+
+
+ Kirk
+
+
+
+
+
+
+ getremove #-end list
+
+
+
+
+ list
+
+
+
+
+
+
+
+ Spock
+
+
+
+
+ McCoy
+
+
+
+
+
+
+ list
+
+
+
+
+
+ Kirk
+
+
+
+
+ Spock
+
+
+
+
+ McCoy
+
+
+
+
+
+
+
+
+ getremove #-end order
+
+
+
+
+
+ GET_REMOVE
+ FROM_END
+ The order for index for #-end is addition because this will catch errors in generators where most perform the operation ... - index.
+
+
+
+
+ TRUE
+
+
+
+
+ list
+
+
+
+
+
+
+
+
+
+ ADD
+
+
+ 0
+
+
+
+
+
+
+ 2
+
+
+
+
+
+
+
+
+
+
+ Kirk
+
+
+
+
+
+
+ getremove #-end order list
+
+
+
+
+ list
+
+
+
+
+
+
+
+ Spock
+
+
+
+
+ McCoy
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ test remove
+ Tests the "remove" block.
+
+
+ list
+
+
@@ -998,14 +3041,18 @@
- remove first list
+
+
+ remove first list
+
+
list
-
+
@@ -1023,7 +3070,7 @@
list
-
+
@@ -1046,31 +3093,47 @@
REMOVE
- LAST
+ FIRST
-
- list
+
+
+
+ TRUE
+
+
+
+
+ list
+
+
+
+
+
- remove last list
+
+
+ remove first order list
+
+
list
-
+
- Kirk
+ Spock
- Spock
+ McCoy
@@ -1079,7 +3142,7 @@
list
-
+
@@ -1102,7 +3165,7 @@
REMOVE
- RANDOM
+ LAST
list
@@ -1110,26 +3173,36 @@
- remove random list
+
+
+ remove last list
+
+
-
-
-
- list
-
-
+
+ list
-
- 2
+
+
+
+
+ Kirk
+
+
+
+
+ Spock
+
+
list
-
+
@@ -1150,29 +3223,40 @@
-
+
REMOVE
- FROM_START
+ LAST
-
- list
-
-
-
-
- 2
+
+
+
+ TRUE
+
+
+
+
+ list
+
+
+
+
+
- remove # list
+
+
+ remove last order list
+
+
list
-
+
@@ -1181,7 +3265,7 @@
- McCoy
+ Spock
@@ -1190,7 +3274,7 @@
list
-
+
@@ -1211,42 +3295,454 @@
-
+
REMOVE
- FROM_END
+ RANDOM
list
-
-
- 3
-
-
- remove #-end list
+
+
+ remove random list
+
+
-
- list
+
+
+
+ list
+
+
-
-
-
-
- Spock
-
-
-
-
- McCoy
-
-
+
+ 2
+
+
+ list
+
+
+
+
+
+ Kirk
+
+
+
+
+ Spock
+
+
+
+
+ McCoy
+
+
+
+
+
+
+
+ REMOVE
+ RANDOM
+
+
+
+
+ TRUE
+
+
+
+
+ list
+
+
+
+
+
+
+
+
+
+
+
+ remove random order list
+
+
+
+
+
+
+ list
+
+
+
+
+
+
+ 2
+
+
+
+
+ list
+
+
+
+
+
+ Kirk
+
+
+
+
+ Spock
+
+
+
+
+ McCoy
+
+
+
+
+
+
+
+ REMOVE
+ FROM_START
+
+
+ list
+
+
+
+
+
+
+ 1
+
+
+
+
+
+
+
+
+ remove # list
+
+
+
+
+ list
+
+
+
+
+
+
+
+ Kirk
+
+
+
+
+ McCoy
+
+
+
+
+
+
+ list
+
+
+
+
+
+ Kirk
+
+
+
+
+ Spock
+
+
+
+
+ McCoy
+
+
+
+
+
+
+
+ REMOVE
+ FROM_START
+
+
+
+
+ TRUE
+
+
+
+
+ list
+
+
+
+
+
+
+
+
+
+
+
+ TRUE
+
+
+
+
+
+
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+ remove # order list
+
+
+
+
+ list
+
+
+
+
+
+
+
+ Kirk
+
+
+
+
+ McCoy
+
+
+
+
+
+
+ list
+
+
+
+
+
+ Kirk
+
+
+
+
+ Spock
+
+
+
+
+ McCoy
+
+
+
+
+
+
+
+ REMOVE
+ FROM_END
+
+
+ list
+
+
+
+
+
+
+ 2
+
+
+
+
+
+
+
+
+ remove #-end list
+
+
+
+
+ list
+
+
+
+
+
+
+
+ Spock
+
+
+
+
+ McCoy
+
+
+
+
+
+
+ list
+
+
+
+
+
+ Kirk
+
+
+
+
+ Spock
+
+
+
+
+ McCoy
+
+
+
+
+
+
+
+ REMOVE
+ FROM_END
+ The order for index for #-end is addition because this will catch errors in generators where most perform the operation ... - index.
+
+
+
+
+ TRUE
+
+
+
+
+ list
+
+
+
+
+
+
+
+
+
+ ADD
+
+
+ 0
+
+
+
+
+
+
+ 2
+
+
+
+
+
+
+
+
+
+
+ remove #-end order list
+
+
+
+
+ list
+
+
+
+
+
+
+
+ Spock
+
+
+
+
+ McCoy
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -1278,14 +3774,14 @@
-
+
test set
- Describe this function...
+ Tests the "set" block.
- x
+ list
-
+
@@ -1311,7 +3807,7 @@
FIRST
- x
+ list
@@ -1321,14 +3817,18 @@
- set first list
+
+
+ set first list
+
+
- x
+ list
-
+
@@ -1349,9 +3849,9 @@
- x
+ list
-
+
@@ -1374,31 +3874,47 @@
SET
- LAST
+ FIRST
-
- x
+
+
+
+ TRUE
+
+
+
+
+ list
+
+
+
+
+
- Beverly
+ Jean-Luc
- set last list
+
+
+ set first order list
+
+
- x
+ list
-
+
- Picard
+ Jean-Luc
@@ -1408,16 +3924,16 @@
- Beverly
+ Crusher
- x
+ list
-
+
@@ -1440,39 +3956,54 @@
SET
- RANDOM
+ LAST
- x
+ list
- Data
+ Beverly
- set random list
+
+
+ set last list
+
+
-
-
-
- x
+
+ list
+
+
+
+
+
+
+
+ Picard
+
+
+
+
+ Riker
+
+
+
+
+ Beverly
-
-
- 3
-
-
- x
+ list
-
+
@@ -1493,34 +4024,45 @@
-
+
SET
- FROM_START
+ LAST
-
- x
-
-
-
-
- 3
+
+
+
+ TRUE
+
+
+
+
+ list
+
+
+
+
+
- Pulaski
+ Beverly
- set # list
+
+
+ set last order list
+
+
- x
+ list
-
+
@@ -1534,16 +4076,16 @@
- Pulaski
+ Beverly
- x
+ list
-
+
@@ -1564,52 +4106,504 @@
-
+
SET
- FROM_END
+ RANDOM
- x
-
-
-
-
- 1
+ list
- Pulaski
+ Data
- set #-end list
+
+
+ set random list
+
+
-
- x
+
+
+
+ list
+
+
-
-
-
-
- Picard
-
-
-
-
- Riker
-
-
-
-
- Pulaski
-
-
+
+ 3
+
+
+ list
+
+
+
+
+
+ Picard
+
+
+
+
+ Riker
+
+
+
+
+ Crusher
+
+
+
+
+
+
+
+ SET
+ RANDOM
+
+
+
+
+ TRUE
+
+
+
+
+ list
+
+
+
+
+
+
+
+
+
+ Data
+
+
+
+
+
+
+ set random order list
+
+
+
+
+
+
+ list
+
+
+
+
+
+
+ 3
+
+
+
+
+ list
+
+
+
+
+
+ Picard
+
+
+
+
+ Riker
+
+
+
+
+ Crusher
+
+
+
+
+
+
+
+ SET
+ FROM_START
+
+
+ list
+
+
+
+
+
+
+ 2
+
+
+
+
+
+
+ Pulaski
+
+
+
+
+
+
+ set # list
+
+
+
+
+ list
+
+
+
+
+
+
+
+ Picard
+
+
+
+
+ Riker
+
+
+
+
+ Pulaski
+
+
+
+
+
+
+ list
+
+
+
+
+
+ Picard
+
+
+
+
+ Riker
+
+
+
+
+ Crusher
+
+
+
+
+
+
+
+ SET
+ FROM_START
+
+
+
+
+ TRUE
+
+
+
+
+ list
+
+
+
+
+
+
+
+
+
+
+
+ TRUE
+
+
+
+
+
+
+ 2
+
+
+
+
+
+
+
+
+
+
+
+ Pulaski
+
+
+
+
+
+
+ set # order list
+
+
+
+
+ list
+
+
+
+
+
+
+
+ Picard
+
+
+
+
+ Riker
+
+
+
+
+ Pulaski
+
+
+
+
+
+
+ list
+
+
+
+
+
+ Picard
+
+
+
+
+ Riker
+
+
+
+
+ Crusher
+
+
+
+
+
+
+
+ SET
+ FROM_END
+
+
+ list
+
+
+
+
+
+
+ 0
+
+
+
+
+
+
+ Pulaski
+
+
+
+
+
+
+ set #-end list
+
+
+
+
+ list
+
+
+
+
+
+
+
+ Picard
+
+
+
+
+ Riker
+
+
+
+
+ Pulaski
+
+
+
+
+
+
+ list
+
+
+
+
+
+ Picard
+
+
+
+
+ Riker
+
+
+
+
+ Crusher
+
+
+
+
+
+
+
+ SET
+ FROM_END
+ The order for index for #-end is addition because this will catch errors in generators where most perform the operation ... - index.
+
+
+
+
+ TRUE
+
+
+
+
+ list
+
+
+
+
+
+
+
+
+
+ ADD
+
+
+ 0
+
+
+
+
+
+
+ 1
+
+
+
+
+
+
+
+
+ Pulaski
+
+
+
+
+
+
+ set #-end order list
+
+
+
+
+ list
+
+
+
+
+
+
+
+ Picard
+
+
+
+
+ Pulaski
+
+
+
+
+ Crusher
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -1641,14 +4635,14 @@
-
+
test insert
- Describe this function...
+ Tests the "insert" block.
- x
+ list
-
+
@@ -1674,7 +4668,7 @@
FIRST
- x
+ list
@@ -1684,14 +4678,18 @@
- insert first list
+
+
+ insert first list
+
+
- x
+ list
-
+
@@ -1717,9 +4715,9 @@
- x
+ list
-
+
@@ -1742,10 +4740,22 @@
INSERT
- LAST
+ FIRST
-
- x
+
+
+
+ TRUE
+
+
+
+
+ list
+
+
+
+
+
@@ -1755,42 +4765,46 @@
- insert last list
+
+
+ insert first order list
+
+
- x
+ list
-
+
- Picard
+ Data
- Riker
+ Picard
- Crusher
+ Riker
- Data
+ Crusher
- x
+ list
-
+
@@ -1813,10 +4827,10 @@
INSERT
- RANDOM
+ LAST
- x
+ list
@@ -1826,26 +4840,46 @@
- insert random list
+
+
+ insert last list
+
+
-
-
-
- x
+
+ list
+
+
+
+
+
+
+
+ Picard
+
+
+
+
+ Riker
+
+
+
+
+ Crusher
+
+
+
+
+ Data
-
-
- 4
-
-
- x
+ list
-
+
@@ -1866,17 +4900,24 @@
-
+
INSERT
- FROM_START
+ LAST
-
- x
-
-
-
-
- 3
+
+
+
+ TRUE
+
+
+
+
+ list
+
+
+
+
+
@@ -1886,14 +4927,18 @@
- insert # list
+
+
+ insert last order list
+
+
- x
+ list
-
+
@@ -1907,21 +4952,21 @@
- Data
+ Crusher
- Crusher
+ Data
- x
+ list
-
+
@@ -1942,17 +4987,12 @@
-
+
INSERT
- FROM_END
+ RANDOM
- x
-
-
-
-
- 1
+ list
@@ -1962,37 +5002,509 @@
- insert #-end list
+
+
+ insert random list
+
+
-
- x
+
+
+
+ list
+
+
-
-
-
-
- Picard
-
-
-
-
- Riker
-
-
-
-
- Data
-
-
-
-
- Crusher
-
-
+
+ 4
+
+
+ list
+
+
+
+
+
+ Picard
+
+
+
+
+ Riker
+
+
+
+
+ Crusher
+
+
+
+
+
+
+
+ INSERT
+ RANDOM
+
+
+
+
+ TRUE
+
+
+
+
+ list
+
+
+
+
+
+
+
+
+
+ Data
+
+
+
+
+
+
+ insert random order list
+
+
+
+
+
+
+ list
+
+
+
+
+
+
+ 4
+
+
+
+
+ list
+
+
+
+
+
+ Picard
+
+
+
+
+ Riker
+
+
+
+
+ Crusher
+
+
+
+
+
+
+
+ INSERT
+ FROM_START
+
+
+ list
+
+
+
+
+
+
+ 2
+
+
+
+
+
+
+ Data
+
+
+
+
+
+
+ insert # list
+
+
+
+
+ list
+
+
+
+
+
+
+
+ Picard
+
+
+
+
+ Riker
+
+
+
+
+ Data
+
+
+
+
+ Crusher
+
+
+
+
+
+
+ list
+
+
+
+
+
+ Picard
+
+
+
+
+ Riker
+
+
+
+
+ Crusher
+
+
+
+
+
+
+
+ INSERT
+ FROM_START
+
+
+
+
+ TRUE
+
+
+
+
+ list
+
+
+
+
+
+
+
+
+
+
+
+ TRUE
+
+
+
+
+
+
+ 2
+
+
+
+
+
+
+
+
+
+
+
+ Data
+
+
+
+
+
+
+ insert # order list
+
+
+
+
+ list
+
+
+
+
+
+
+
+ Picard
+
+
+
+
+ Riker
+
+
+
+
+ Data
+
+
+
+
+ Crusher
+
+
+
+
+
+
+ list
+
+
+
+
+
+ Picard
+
+
+
+
+ Riker
+
+
+
+
+ Crusher
+
+
+
+
+
+
+
+ INSERT
+ FROM_END
+
+
+ list
+
+
+
+
+
+
+ 0
+
+
+
+
+
+
+ Data
+
+
+
+
+
+
+ insert #-end list
+
+
+
+
+ list
+
+
+
+
+
+
+
+ Picard
+
+
+
+
+ Riker
+
+
+
+
+ Data
+
+
+
+
+ Crusher
+
+
+
+
+
+
+ list
+
+
+
+
+
+ Picard
+
+
+
+
+ Riker
+
+
+
+
+ Crusher
+
+
+
+
+
+
+
+ INSERT
+ FROM_END
+ The order for index for #-end is addition because this will catch errors in generators where most perform the operation ... - index.
+
+
+
+
+ TRUE
+
+
+
+
+ list
+
+
+
+
+
+
+
+
+
+ ADD
+
+
+ 0
+
+
+
+
+
+
+ 1
+
+
+
+
+
+
+
+
+ Data
+
+
+
+
+
+
+ insert #-end order list
+
+
+
+
+ list
+
+
+
+
+
+
+
+ Picard
+
+
+
+
+ Data
+
+
+
+
+ Riker
+
+
+
+
+ Crusher
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -2024,14 +5536,14 @@
-
- test sublist
- Describe this function...
+
+ test sublist simple
+ Tests the "get sub-list" block with a variable.
list
-
+
@@ -2062,7 +5574,11 @@
- sublist # start
+
+
+ sublist # simple
+
+
@@ -2074,19 +5590,27 @@
-
- 2
+
+
+
+ 1
+
+
-
- 3
+
+
+
+ 2
+
+
-
+
@@ -2102,64 +5626,782 @@
- sublist # end
+
+
+ sublist # simple order
+
+
- FROM_END
- FROM_END
+ FROM_START
+ FROM_START
list
-
- 3
+
+
+
+ TRUE
+
+
+
+
+
+
+ 1
+
+
+
+
+
+
+
-
- 2
+
+
+
+ TRUE
+
+
+
+
+
+
+ 2
+
+
+
+
+
+
+
-
+
- Discovery
+ Challenger
- Atlantis
+ Discovery
- sublist first-last
+
+
+ sublist #-end simple
+
+
-
- FIRST
- LAST
+
+ FROM_END
+ FROM_END
list
+
+
+
+
+ 2
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
-
- list
+
+
+
+
+ Discovery
+
+
+
+
+ Atlantis
+
+
+
+
+
+
+ sublist #-end simple order
+
+
+
+
+
+ FROM_END
+ FROM_END
+ The order for index for #-end is addition because this will catch errors in generators where most perform the operation ... - index.
+
+
+ list
+
+
+
+
+ ADD
+
+
+ 0
+
+
+
+
+
+
+ 2
+
+
+
+
+
+
+
+
+ ADD
+
+
+ 0
+
+
+
+
+
+
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Discovery
+
+
+
+
+ Atlantis
+
+
+
+
+
+
+
+
+ sublist first-last simple
+
+
+
+
+
+ FIRST
+ LAST
+
+
+ list
+
+
+
+
+
+
+ list
+
+
+
+
+ changing list
+
+
+
+
+
+ Columbia
+
+
+
+
+ Challenger
+
+
+
+
+ Discovery
+
+
+
+
+ Atlantis
+
+
+
+
+ Endeavour
+
+
+
+
+
+
+ list copy
+
+
+
+ FIRST
+ LAST
+
+
+ changing list
+
+
+
+
+
+
+
+ REMOVE
+ RANDOM
+
+
+ changing list
+
+
+
+
+
+
+ sublist first-last simple copy check
+
+
+
+
+ list copy
+
+
+
+
+ list
+
+
+
+
+
+
+ sublist # #-end simple
+
+
+
+
+
+ FROM_START
+ FROM_END
+
+
+ list
+
+
+
+
+
+
+ 1
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+
+
+
+
+
+
+
+ Challenger
+
+
+
+
+ Discovery
+
+
+
+
+ Atlantis
+
+
+
+
+
+
+
+
+ sublist #-end # simple
+
+
+
+
+
+ FROM_END
+ FROM_START
+
+
+ list
+
+
+
+
+
+
+ 2
+
+
+
+
+
+
+
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+ Discovery
+
+
+
+
+ Atlantis
+
+
+
+
+
+
+
+
+ sublist first # simple
+
+
+
+
+
+ FIRST
+ FROM_START
+
+
+ list
+
+
+
+
+
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+ Columbia
+
+
+
+
+ Challenger
+
+
+
+
+ Discovery
+
+
+
+
+ Atlantis
+
+
+
+
+
+
+
+
+ sublist first #-end simple
+
+
+
+
+
+ FIRST
+ FROM_END
+
+
+ list
+
+
+
+
+
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+ Columbia
+
+
+
+
+ Challenger
+
+
+
+
+
+
+
+
+ sublist # last simple
+
+
+
+
+
+ FROM_START
+ LAST
+
+
+ list
+
+
+
+
+
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+ Atlantis
+
+
+
+
+ Endeavour
+
+
+
+
+
+
+
+
+ sublist #-end last simple
+
+
+
+
+
+ FROM_END
+ LAST
+
+
+ list
+
+
+
+
+
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+ Challenger
+
+
+
+
+ Discovery
+
+
+
+
+ Atlantis
+
+
+
+
+ Endeavour
+
+
+
+
+
+
+
+
+ sublist all with # #-end simple
+
+
+
+
+
+ FROM_START
+ FROM_END
+
+
+ list
+
+
+
+
+
+
+ 0
+
+
+
+
+
+
+
+
+ 0
+
+
+
+
+
+
+
+
+ list
+
+
+
+
+
+
+ sublist all with #-end # simple
+
+
+
+
+
+ FROM_END
+ FROM_START
+
+
+ list
+
+
+
+
+
+
+ 4
+
+
+
+
+
+
+
+
+ 4
+
+
+
+
+
+
+
+
+ list
+
+
+
+
+
+
+ sublist all with # #-end math simple
+
+
+
+
+
+ FROM_START
+ FROM_END
+ Checks that the whole list is properly retrieved even if the value for start and end is not a simple number. This is especially important in generators where sublist uses [x:length - y] for # #-end.
+
+
+ list
+
+
+
+
+ ADD
+
+
+ 0
+
+
+
+
+
+
+ 0
+
+
+
+
+
+
+
+
+ ADD
+
+
+ 0
+
+
+
+
+
+
+ 0
+
+
+
+
+
+
+
+
+
+
+ list
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -2169,14 +6411,1154 @@
-
- test join
- Describe this function...
+
+ get space shuttles
+ Creates a list for use with the sublist test.
-
+
+ number of calls
+
+
+ 1
+
+
+
+
+
+
+
+
+
+ Columbia
+
+
+
+
+ Challenger
+
+
+
+
+ Discovery
+
+
+
+
+ Atlantis
+
+
+
+
+ Endeavour
+
+
+
+
+
+
+ test sublist complex
+ Tests the "get sub-list" block with a function call.
+
+
+ number of calls
+
+
+ 0
+
+
+
+
+
+
+ sublist # start complex
+
+
+
+
+
+ FROM_START
+ FROM_START
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+
+
+
+
+ 2
+
+
+
+
+
+
+
+
+
+
+
+ Challenger
+
+
+
+
+ Discovery
+
+
+
+
+
+
+
+
+
+
+
+ sublist # start complex
+
+
+
+
+ number of calls
+
+
+ 0
+
+
+
+
+
+
+ sublist # start order complex
+
+
+
+
+
+ FROM_START
+ FROM_START
+
+
+
+
+ TRUE
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ TRUE
+
+
+
+
+
+
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+ TRUE
+
+
+
+
+
+
+ 2
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Challenger
+
+
+
+
+ Discovery
+
+
+
+
+
+
+
+
+
+
+
+ sublist # start order complex
+
+
+
+
+ number of calls
+
+
+ 0
+
+
+
+
+
+
+ sublist # end complex
+
+
+
+
+
+ FROM_END
+ FROM_END
+ The order for index for #-end is addition because this will catch errors in generators where most perform the operation ... - index.
+
+
+
+
+
+
+
+
+
+ 2
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+
+
+
+
+
+
+
+ Discovery
+
+
+
+
+ Atlantis
+
+
+
+
+
+
+
+
+ sublist # end complex number of calls
+
+
+
+
+ number of calls
+
+
+
+
+ 1
+
+
+
+
+ number of calls
+
+
+ 0
+
+
+
+
+
+
+ sublist # end order complex
+
+
+
+
+
+ FROM_END
+ FROM_END
+
+
+
+
+ TRUE
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ADD
+
+
+ 0
+
+
+
+
+
+
+ 2
+
+
+
+
+
+
+
+
+ ADD
+
+
+ 0
+
+
+
+
+
+
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Discovery
+
+
+
+
+ Atlantis
+
+
+
+
+
+
+
+
+
+
+
+ sublist # end order complex
+
+
+
+
+ number of calls
+
+
+ 0
+
+
+
+
+
+
+ sublist first-last complex
+
+
+
+
+
+ FIRST
+ LAST
+
+
+
+
+
+
+
+
+
+ list
+
+
+
+
+
+
+
+
+
+ sublist first-last complex
+
+
+
+
+ number of calls
+
+
+ 0
+
+
+
+
+
+
+ sublist # #-end complex
+
+
+
+
+
+ FROM_START
+ FROM_END
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+
+
+
+
+
+
+
+ Challenger
+
+
+
+
+ Discovery
+
+
+
+
+ Atlantis
+
+
+
+
+
+
+
+
+
+
+
+ sublist # #-end complex
+
+
+
+
+ number of calls
+
+
+ 0
+
+
+
+
+
+
+ sublist #-end # complex
+
+
+
+
+
+ FROM_END
+ FROM_START
+
+
+
+
+
+
+
+
+
+ 2
+
+
+
+
+
+
+
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+ Discovery
+
+
+
+
+ Atlantis
+
+
+
+
+
+
+
+
+
+
+
+ sublist #-end # complex
+
+
+
+
+ number of calls
+
+
+ 0
+
+
+
+
+
+
+ sublist first # complex
+
+
+
+
+
+ FIRST
+ FROM_START
+
+
+
+
+
+
+
+
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+ Columbia
+
+
+
+
+ Challenger
+
+
+
+
+ Discovery
+
+
+
+
+ Atlantis
+
+
+
+
+
+
+
+
+
+
+
+ sublist first # complex
+
+
+
+
+ number of calls
+
+
+ 0
+
+
+
+
+
+
+ sublist first #-end complex
+
+
+
+
+
+ FIRST
+ FROM_END
+
+
+
+
+
+
+
+
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+ Columbia
+
+
+
+
+ Challenger
+
+
+
+
+
+
+
+
+
+
+
+ sublist first #-end complex
+
+
+
+
+ number of calls
+
+
+ 0
+
+
+
+
+
+
+ sublist # last complex
+
+
+
+
+
+ FROM_START
+ LAST
+
+
+
+
+
+
+
+
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+ Atlantis
+
+
+
+
+ Endeavour
+
+
+
+
+
+
+
+
+
+
+
+ sublist # last complex
+
+
+
+
+ number of calls
+
+
+ 0
+
+
+
+
+
+
+ sublist #-end last simple
+
+
+
+
+
+ FROM_END
+ LAST
+
+
+
+
+
+
+
+
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+ Challenger
+
+
+
+
+ Discovery
+
+
+
+
+ Atlantis
+
+
+
+
+ Endeavour
+
+
+
+
+
+
+
+
+
+
+
+ sublist #-end last simple
+
+
+
+
+ number of calls
+
+
+ 0
+
+
+
+
+
+
+ sublist all with # #-end complex
+
+
+
+
+
+ FROM_START
+ FROM_END
+
+
+
+
+
+
+
+
+
+ 0
+
+
+
+
+
+
+
+
+ 0
+
+
+
+
+
+
+
+
+ list
+
+
+
+
+
+
+
+
+
+ sublist all with # #-end complex
+
+
+
+
+ number of calls
+
+
+ 0
+
+
+
+
+
+
+ sublist all with #-end # complex
+
+
+
+
+
+ FROM_END
+ FROM_START
+
+
+
+
+
+
+
+
+
+ 4
+
+
+
+
+
+
+
+
+ 4
+
+
+
+
+
+
+
+
+ list
+
+
+
+
+
+
+
+
+
+ sublist all with #-end # complex
+
+
+
+
+ number of calls
+
+
+ 0
+
+
+
+
+
+
+ sublist all with # #-end math complex
+
+
+
+
+
+ FROM_START
+ FROM_END
+ Checks that the whole list is properly retrieved even if the value for start and end is not a simple number. This is especially important in generators where sublist uses [x:length - y] for # #-end.
+
+
+
+
+
+
+
+ ADD
+
+
+ 0
+
+
+
+
+
+
+ 0
+
+
+
+
+
+
+
+
+ ADD
+
+
+ 0
+
+
+
+
+
+
+ 0
+
+
+
+
+
+
+
+
+
+
+ list
+
+
+
+
+
+
+
+
+
+ sublist all with # #-end math complex
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ test join
+ Tests the "join" block.
+
+
list
-
+
@@ -2197,7 +7579,11 @@
- join
+
+
+ join
+
+
@@ -2219,43 +7605,89 @@
Vulcan,Klingon,Borg
+
+
+
+
+ join order
+
+
+
+
+
+ JOIN
+
+
+
+
+ TRUE
+
+
+
+
+ list
+
+
+
+
+
+
+
+
+
+ ,
+
+
+
+
+
+
+ Vulcan,Klingon,Borg
+
+
+
+
-
+
test split
- Describe this function...
+ Tests the "split" block.
-
- list
+
+ text
-
-
- SPLIT
-
-
- Vulcan,Klingon,Borg
-
-
-
-
- ,
-
-
+
+ Vulcan,Klingon,Borg
- split
+
+
+ split
+
+
-
- list
+
+
+ SPLIT
+
+
+ text
+
+
+
+
+ ,
+
+
-
+
@@ -2274,53 +7706,114 @@
+
+
+
+
+ split order
+
+
+
+
+
+ SPLIT
+
+
+
+
+ TRUE
+
+
+
+
+ text
+
+
+
+
+
+
+
+
+
+ ,
+
+
+
+
+
+
+
+
+
+ Vulcan
+
+
+
+
+ Klingon
+
+
+
+
+ Borg
+
+
+
+
+
+
-
+
test sort alphabetic
- Describe this function...
+ Tests the "alphabetic sort" block.
-
+
list
-
- TEXT
- 1
-
-
-
-
-
- Vulcan
-
-
-
-
- klingon
-
-
-
-
- Borg
-
-
+
+
+
+
+ Vulcan
+
+
+
+
+ klingon
+
+
+
+
+ Borg
- sort alphabetic ascending
+
+
+ sort alphabetic ascending
+
+
-
- list
+
+ TEXT
+ 1
+
+
+ list
+
+
-
+
@@ -2339,53 +7832,109 @@
+
+
+
+
+ sort alphabetic ascending order
+
+
+
+
+ TEXT
+ 1
+
+
+
+
+ TRUE
+
+
+
+
+ list
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Borg
+
+
+
+
+ Vulcan
+
+
+
+
+ klingon
+
+
+
+
+
+
-
+
test sort ignoreCase
- Describe this function...
+ Tests the "alphabetic sort ignore case" block.
-
+
list
-
- IGNORE_CASE
- 1
-
-
-
-
-
- Vulcan
-
-
-
-
- klingon
-
-
-
-
- Borg
-
-
+
+
+
+
+ Vulcan
+
+
+
+
+ klingon
+
+
+
+
+ Borg
- sort ignore case ascending
+
+
+ sort ignore case ascending
+
+
-
- list
+
+ IGNORE_CASE
+ 1
+
+
+ list
+
+
-
+
@@ -2404,53 +7953,109 @@
+
+
+
+
+ sort ignore case ascending order
+
+
+
+
+ IGNORE_CASE
+ 1
+
+
+
+
+ TRUE
+
+
+
+
+ list
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Borg
+
+
+
+
+ klingon
+
+
+
+
+ Vulcan
+
+
+
+
+
+
-
+
test sort numeric
- Describe this function...
+ Tests the "numeric sort" block.
-
+
list
-
- NUMERIC
- -1
-
-
-
-
-
- 8
-
-
-
-
- 18
-
-
-
-
- -1
-
-
+
+
+
+
+ 8
+
+
+
+
+ 18
+
+
+
+
+ -1
- sort numeric descending
+
+
+ sort numeric descending
+
+
-
- list
+
+ NUMERIC
+ -1
+
+
+ list
+
+
-
+
@@ -2469,9 +8074,61 @@
+
+
+
+
+ sort numeric descending order
+
+
+
+
+ NUMERIC
+ -1
+
+
+
+
+ TRUE
+
+
+
+
+ list
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 18
+
+
+
+
+ 8
+
+
+
+
+ -1
+
+
+
+
+
+
-
+
\ No newline at end of file
diff --git a/tests/generators/logic.xml b/tests/generators/logic.xml
index b702b5ee3..acea1c752 100644
--- a/tests/generators/logic.xml
+++ b/tests/generators/logic.xml
@@ -2,7 +2,11 @@
- True
+
+
+ True
+
+
TRUE
@@ -11,7 +15,11 @@
- False
+
+
+ False
+
+
FALSE
@@ -20,7 +28,11 @@
- Not true
+
+
+ Not true
+
+
TRUE
@@ -33,7 +45,11 @@
- Not false
+
+
+ Not false
+
+
FALSE
@@ -89,7 +105,7 @@
- if false
+ if false
@@ -119,7 +135,11 @@
- if true
+
+
+ if true
+
+
TRUE
@@ -144,7 +164,7 @@
- if/else false
+ if/else false
@@ -159,7 +179,11 @@
- if/else false
+
+
+ if/else false
+
+
TRUE
@@ -194,12 +218,16 @@
- if/else true
+ if/else true
- if/else true
+
+
+ if/else true
+
+
TRUE
@@ -224,7 +252,7 @@
- elseif 1
+ elseif 1
@@ -249,17 +277,21 @@
- elseif 2
+ elseif 2
- elseif 3
+ elseif 3
- elseif 4
+
+
+ elseif 4
+
+
TRUE
@@ -297,7 +329,11 @@
test equalities
- Equal yes
+
+
+ Equal yes
+
+
TRUE
@@ -316,7 +352,11 @@
- Equal no
+
+
+ Equal no
+
+
FALSE
@@ -335,7 +375,11 @@
- Not equal yes
+
+
+ Not equal yes
+
+
TRUE
@@ -354,7 +398,11 @@
- Not equal no
+
+
+ Not equal no
+
+
FALSE
@@ -373,7 +421,11 @@
- Smaller yes
+
+
+ Smaller yes
+
+
TRUE
@@ -392,7 +444,11 @@
- Smaller no
+
+
+ Smaller no
+
+
FALSE
@@ -411,7 +467,11 @@
- Greater yes
+
+
+ Greater yes
+
+
TRUE
@@ -430,7 +490,11 @@
- Greater no
+
+
+ Greater no
+
+
FALSE
@@ -449,7 +513,11 @@
- Smaller-equal yes
+
+
+ Smaller-equal yes
+
+
TRUE
@@ -468,7 +536,11 @@
- Smaller-equal no
+
+
+ Smaller-equal no
+
+
FALSE
@@ -487,7 +559,11 @@
- Greater-equal yes
+
+
+ Greater-equal yes
+
+
TRUE
@@ -506,7 +582,11 @@
- Greater-equal no
+
+
+ Greater-equal no
+
+
FALSE
@@ -552,7 +632,11 @@
test or
- Or true/true
+
+
+ Or true/true
+
+
TRUE
@@ -571,7 +655,11 @@
- Or false/true
+
+
+ Or false/true
+
+
TRUE
@@ -590,7 +678,11 @@
- Or true/false
+
+
+ Or true/false
+
+
TRUE
@@ -609,7 +701,11 @@
- Or false/false
+
+
+ Or false/false
+
+
FALSE
@@ -639,7 +735,11 @@
test and
- And true/true
+
+
+ And true/true
+
+
TRUE
@@ -658,7 +758,11 @@
- And false/true
+
+
+ And false/true
+
+
FALSE
@@ -677,7 +781,11 @@
- And true/false
+
+
+ And true/false
+
+
FALSE
@@ -696,7 +804,11 @@
- And false/false
+
+
+ And false/false
+
+
FALSE
@@ -726,7 +838,11 @@
test ternary
- if true
+
+
+ if true
+
+
@@ -753,7 +869,11 @@
- if true
+
+
+ if true
+
+
diff --git a/tests/generators/loops1.xml b/tests/generators/loops1.xml
index 70fb34c1c..7cdff0786 100644
--- a/tests/generators/loops1.xml
+++ b/tests/generators/loops1.xml
@@ -62,7 +62,11 @@
- for loop
+
+
+ for loop
+
+
log
@@ -93,7 +97,7 @@
- while 0
+ while 0
@@ -106,7 +110,7 @@
- until 0
+ until 0
@@ -147,7 +151,11 @@
- while 10
+
+
+ while 10
+
+
count
@@ -196,7 +204,11 @@
- until 10
+
+
+ until 10
+
+
count
@@ -254,7 +266,11 @@
- repeat 10
+
+
+ repeat 10
+
+
count
diff --git a/tests/generators/loops2.xml b/tests/generators/loops2.xml
index 4307f6d10..c35623a5d 100644
--- a/tests/generators/loops2.xml
+++ b/tests/generators/loops2.xml
@@ -51,7 +51,11 @@
- count up ints
+
+
+ count up ints
+
+
log
@@ -100,7 +104,11 @@
- count down ints
+
+
+ count down ints
+
+
log
@@ -154,7 +162,11 @@
- count with floats
+
+
+ count with floats
+
+
loglist
@@ -263,7 +275,11 @@
- count up non-trivial ints
+
+
+ count up non-trivial ints
+
+
loglist
@@ -377,7 +393,11 @@
- count down non-trivial ints
+
+
+ count down non-trivial ints
+
+
loglist
@@ -481,7 +501,11 @@
- count with floats
+
+
+ count with floats
+
+
loglist
@@ -589,7 +613,11 @@
- count up
+
+
+ count up
+
+
log
@@ -633,7 +661,11 @@
- count down
+
+
+ count down
+
+
log
@@ -702,7 +734,11 @@
- count up non-trivial
+
+
+ count up non-trivial
+
+
loglist
@@ -791,7 +827,11 @@
- count down non-trivial
+
+
+ count down non-trivial
+
+
loglist
diff --git a/tests/generators/loops3.xml b/tests/generators/loops3.xml
index 6cd5e0c75..508b88729 100644
--- a/tests/generators/loops3.xml
+++ b/tests/generators/loops3.xml
@@ -93,7 +93,11 @@
- while continue
+
+
+ while continue
+
+
log
@@ -184,7 +188,11 @@
- until continue
+
+
+ until continue
+
+
log
@@ -252,7 +260,11 @@
- count continue
+
+
+ count continue
+
+
log
@@ -335,7 +347,11 @@
- for continue
+
+
+ for continue
+
+
log
@@ -439,7 +455,11 @@
- while break
+
+
+ while break
+
+
count
@@ -512,7 +532,11 @@
- until break
+
+
+ until break
+
+
count
@@ -580,7 +604,11 @@
- count break
+
+
+ count break
+
+
log
@@ -663,7 +691,11 @@
- for break
+
+
+ for break
+
+
log
diff --git a/tests/generators/math.xml b/tests/generators/math.xml
index 38b28c3b5..9c1f644f8 100644
--- a/tests/generators/math.xml
+++ b/tests/generators/math.xml
@@ -1,11 +1,11 @@
-
+
-
+
@@ -61,11 +61,16 @@
-
- test operations on single
+
+ test single
+ Tests the "single" block.
- sqrt
+
+
+ sqrt
+
+
ROOT
@@ -83,7 +88,11 @@
- abs
+
+
+ abs
+
+
ABS
@@ -101,7 +110,11 @@
- negate
+
+
+ negate
+
+
NEG
@@ -119,7 +132,11 @@
- ln
+
+
+ ln
+
+
LN
@@ -137,7 +154,11 @@
- log10
+
+
+ log10
+
+
LOG10
@@ -155,7 +176,11 @@
- exp
+
+
+ exp
+
+
EXP
@@ -173,7 +198,11 @@
- power10
+
+
+ power10
+
+
POW10
@@ -204,11 +233,16 @@
-
+
test arithmetic
+ Tests the "arithmetic" block for all operations and checks parenthesis are properly generated for different orders.
- add
+
+
+ add
+
+
ADD
@@ -231,7 +265,11 @@
- subtract
+
+
+ subtract
+
+
MINUS
@@ -254,73 +292,280 @@
- multiply
+
+
+ subtract order with add
+
+
- MULTIPLY
+ MINUS
- 4
+ 1
-
- 2.5
+
+ ADD
+
+
+ 0
+
+
+
+
+ 2
+
+
- 10
+ -1
- divide
+
+
+ subtract order with subtract
+
+
- DIVIDE
+ MINUS
- 8.2
+ 1
-
- -5
+
+ MINUS
+
+
+ 0
+
+
+
+
+ 2
+
+
- -1.64
+ 3
- power
+
+
+ multiply
+
+
- POWER
+ MULTIPLY
- 10
+ 4
- 4
+ 2.5
- 10000
+ 10
+
+
+
+
+ multiply order
+
+
+
+
+ MULTIPLY
+
+
+ 4
+
+
+
+
+ ADD
+
+
+ 0
+
+
+
+
+ 2.5
+
+
+
+
+
+
+
+
+ 10
+
+
+
+
+
+
+ divide
+
+
+
+
+ DIVIDE
+
+
+ 8.2
+
+
+
+
+ -5
+
+
+
+
+
+
+ -1.64
+
+
+
+
+
+
+ divide order
+
+
+
+
+ DIVIDE
+
+
+ 8.2
+
+
+
+
+ ADD
+
+
+ 0
+
+
+
+
+ -5
+
+
+
+
+
+
+
+
+ -1.64
+
+
+
+
+
+
+ power
+
+
+
+
+ POWER
+
+
+ 10
+
+
+
+
+ 4
+
+
+
+
+
+
+ 10000
+
+
+
+
+
+
+ power order
+
+
+
+
+ POWER
+
+
+ 10
+
+
+
+
+ ADD
+
+
+ 0
+
+
+
+
+ 4
+
+
+
+
+
+
+
+
+ 10000
+
+
+
+
+
+
+
+
+
+
+
+
@@ -332,11 +577,16 @@
-
+
test trig
+ Tests the "trig" block.
- sin
+
+
+ sin
+
+
SIN
@@ -354,7 +604,11 @@
- cos
+
+
+ cos
+
+
COS
@@ -372,7 +626,11 @@
- tan
+
+
+ tan
+
+
TAN
@@ -390,7 +648,11 @@
- asin
+
+
+ asin
+
+
ASIN
@@ -408,7 +670,11 @@
- acos
+
+
+ acos
+
+
ACOS
@@ -426,7 +692,11 @@
- atan
+
+
+ atan
+
+
ATAN
@@ -455,11 +725,16 @@
-
+
test constant
+ Tests the "constant" blocks.
- const pi
+
+
+ const pi
+
+
ROUNDDOWN
@@ -487,7 +762,11 @@
- const e
+
+
+ const e
+
+
ROUNDDOWN
@@ -515,7 +794,11 @@
- const golden
+
+
+ const golden
+
+
ROUNDDOWN
@@ -543,7 +826,11 @@
- const sqrt 2
+
+
+ const sqrt 2
+
+
ROUNDDOWN
@@ -571,7 +858,11 @@
- const sqrt 0.5
+
+
+ const sqrt 0.5
+
+
ROUNDDOWN
@@ -599,8 +890,12 @@
- const infinity
TRUE
+
+
+ const infinity
+
+
LT
@@ -629,12 +924,17 @@
-
+
test number properties
+ Tests the "number property" blocks.
- even
TRUE
+
+
+ even
+
+
@@ -648,8 +948,12 @@
- odd
FALSE
+
+
+ odd
+
+
@@ -663,8 +967,12 @@
- prime 5
TRUE
+
+
+ prime 5
+
+
@@ -678,8 +986,12 @@
- prime 25
FALSE
+
+
+ prime 25
+
+
@@ -693,8 +1005,12 @@
- prime negative
FALSE
+
+
+ prime negative
+
+
@@ -708,8 +1024,12 @@
- whole
FALSE
+
+
+ whole
+
+
@@ -723,8 +1043,12 @@
- positive
TRUE
+
+
+ positive
+
+
@@ -738,8 +1062,12 @@
- negative
TRUE
+
+
+ negative
+
+
@@ -753,8 +1081,12 @@
- divisible
TRUE
+
+
+ divisible
+
+
@@ -790,11 +1122,16 @@
-
+
test round
+ Tests the "round" block.
- round
+
+
+ round
+
+
ROUND
@@ -812,7 +1149,11 @@
- round up
+
+
+ round up
+
+
ROUNDUP
@@ -830,7 +1171,11 @@
- round down
+
+
+ round down
+
+
ROUNDDOWN
@@ -853,8 +1198,9 @@
-
+
test change
+ Tests the "change" block.
varToChange
@@ -873,7 +1219,11 @@
- change
+
+
+ change
+
+
varToChange
@@ -891,176 +1241,16 @@
-
-
-
-
-
- assert list equal
-
-
- equal
-
-
- TRUE
-
-
-
-
-
-
-
- NEQ
-
-
-
-
- a
-
-
-
-
-
-
-
-
- b
-
-
-
-
-
-
-
-
- equal
-
-
- FALSE
-
-
-
-
-
-
- x
-
-
- 1
-
-
-
-
-
-
- a
-
-
-
-
-
-
-
-
- NEQ
-
-
-
- GET
- FROM_START
-
-
- a
-
-
-
-
- x
-
-
-
-
-
-
-
- GET
- FROM_START
-
-
- b
-
-
-
-
- x
-
-
-
-
-
-
-
-
- equal
-
-
- FALSE
-
-
-
-
- BREAK
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- equal
-
-
-
-
-
-
- list equality
-
-
- a
-
-
-
-
- b
-
-
-
-
-
-
-
-
-
-
-
-
- equal
-
-
-
-
+
test operations on list
+ Tests the "list operation" blocks.
- sum
+
+
+ sum
+
+
@@ -1094,7 +1284,11 @@
- min
+
+
+ min
+
+
@@ -1128,7 +1322,11 @@
- max
+
+
+ max
+
+
@@ -1162,7 +1360,11 @@
- average
+
+
+ average
+
+
@@ -1196,7 +1398,11 @@
- median
+
+
+ median
+
+
@@ -1234,22 +1440,62 @@
-
- modes
- TRUE
+
+
+
+ modes
+
+
-
-
-
-
-
-
+
+
+ MODE
+
+
+
+
+
+ 3
+
+
+
+
+ 4
+
+
+
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+ 3
+
+
+
+
+
+
+
+
+ modes multiple
+
+
+
MODE
-
+
3
@@ -1265,45 +1511,14 @@
3
-
-
-
-
-
-
-
-
-
- 3
-
-
-
-
-
-
-
-
- standard dev
-
-
-
- STD_DEV
-
-
-
-
+
- 3
+ 1
-
+
- 3
-
-
-
-
- 3
+ 4
@@ -1311,46 +1526,74 @@
-
- 0
+
+
+
+
+ 3
+
+
+
+
+ 4
+
+
-
- random
- TRUE
+
+
+
+ standard dev
+
+
-
- GT
-
-
- FIRST
-
-
-
-
-
- 3
-
-
-
-
- 4
-
-
-
-
- 5
-
-
+
+
+ STD_DEV
+
+
+
+
+
+ 3
-
-
-
- RANDOM
-
-
+
+
+ 3
+
+
+
+
+ 3
+
+
+
+
+
+
+
+
+ 0
+
+
+
+
+ TRUE
+
+
+ random
+
+
+
+
+ GT
+
+
+ FIRST
+
+
@@ -1369,17 +1612,43 @@
+
+
+
+ RANDOM
+
+
+
+
+
+ 3
+
+
+
+
+ 4
+
+
+
+
+ 5
+
+
+
+
+
+
+
+
+
+
+ 0
-
-
- 0
-
-
-
+
@@ -1397,11 +1666,16 @@
-
+
test mod
+ Tests the "mod" block.
- mod
+
+
+ mod
+
+
@@ -1424,11 +1698,16 @@
-
+
test constraint
+ Tests the "constrain" block.
- constraint
+
+
+ constraint
+
+
@@ -1456,8 +1735,9 @@
-
+
test random integer
+ Tests the "random integer" block.
rand
@@ -1477,8 +1757,12 @@
- randRange
TRUE
+
+
+ randRange
+
+
AND
@@ -1516,8 +1800,12 @@
- randInteger
TRUE
+
+
+ randInteger
+
+
@@ -1536,8 +1824,9 @@
-
+
test random fraction
+ Tests the "random fraction" block.
rand
@@ -1546,8 +1835,12 @@
- randFloat
TRUE
+
+
+ randFloat
+
+
AND
@@ -1588,4 +1881,4 @@
-
+
\ No newline at end of file
diff --git a/tests/generators/text.xml b/tests/generators/text.xml
index 39a5879a9..baf62d80f 100644
--- a/tests/generators/text.xml
+++ b/tests/generators/text.xml
@@ -1,32 +1,47 @@
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -46,40 +61,35 @@
-
- test length
+
+
+
+
+ check number of calls
+ Checks that the number of calls is one in order to confirm that a function was only called once.
-
- length
-
-
-
-
- Google
-
-
-
-
-
-
- 6
+
+ test name
+
+
+ number of calls
-
- length
+
+
+
+ test name
+
+
-
-
-
-
-
-
+
+ number of calls
- 0
+ 1
@@ -87,14 +97,238 @@
-
+
+ test create
+ Tests the "create text with" block with varying number of inputs.
+
+
+
+
+ no text
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ create single
+
+
+
+
+
+
+
+ Hello
+
+
+
+
+
+
+ Hello
+
+
+
+
+
+
+ create single number
+
+
+
+
+
+
+
+ -1
+
+
+
+
+
+
+ -1
+
+
+
+
+
+
+ create double text
+
+
+
+
+
+
+
+ K
+
+
+
+
+ 9
+
+
+
+
+
+
+ K9
+
+
+
+
+
+
+ create double text numbers
+
+
+
+
+
+
+
+ 4
+
+
+
+
+ 2
+
+
+
+
+
+
+ 42
+
+
+
+
+
+
+ create triple
+
+
+
+
+
+
+
+ 1
+
+
+
+
+ 2
+
+
+
+
+ 3
+
+
+
+
+
+
+ 123
+
+
+
+
+
+
+ create order
+
+
+
+
+
+
+
+ 1
+
+
+
+
+
+
+ TRUE
+
+
+
+
+ 0
+
+
+
+
+
+
+
+
+
+ M
+
+
+
+
+
+
+ 10M
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ get empty
+ Creates an empty string for use with the empty test.
+
+
+
+
+
+
+
test empty
+ Tests the "is empty" block".
- not empty
FALSE
+
+
+ not empty
+
+
-
+
Google
@@ -104,10 +338,14 @@
- empty
TRUE
+
+
+ empty
+
+
-
+
@@ -115,80 +353,137 @@
+
+
+ TRUE
+
+
+ empty complex
+
+
+
+
+
+
+
+
+
+
+
+
+
+ TRUE
+
+
+ empty order
+
+
+
+
+
+
+
+
+ TRUE
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
- test create text
+
+ test length
+ Tests the "length" block.
- single text
+
+
+ zero length
+
+
-
-
-
+
+
- Hello
+
-
- Hello
+
+ 0
- double text
+
+
+ non-zero length
+
+
-
-
-
+
+
- K
-
-
-
-
- 9
+ Google
-
- K9
+
+ 6
- triple text
+
+
+ length order
+
+
-
-
-
-
- 1
-
-
-
-
- 2
-
-
-
-
- 3
+
+
+
+
+
+ TRUE
+
+
+
+
+ car
+
+
+
+
+
-
- 123
+
+ 3
@@ -198,8 +493,9 @@
-
- test append item
+
+ test append
+ Tests the "append text" block with different types of parameters.
item
@@ -218,7 +514,11 @@
- append text
+
+
+ append text
+
+
item
@@ -247,7 +547,11 @@
- append number
+
+
+ append number
+
+
item
@@ -258,6 +562,57 @@
1234
+
+
+ item
+
+
+ Something
+
+
+
+
+ item
+
+
+
+
+ TRUE
+
+
+
+
+ Positive
+
+
+
+
+
+
+
+
+
+
+
+ append order
+
+
+
+
+ item
+
+
+
+
+ Something Positive
+
+
+
+
+
+
+
+
@@ -271,94 +626,108 @@
-
- test substring
+
+ test find simple
+ Tests the "find" block with a variable.
text
- 123456789
+ Banana
- substring # start
+
+
+ find first simple
+
+
-
-
- FROM_START
- FROM_START
-
+
+ FIRST
+
text
-
-
- 2
-
-
-
-
- 3
+
+
+ an
-
- 23
+
+
+
+ 1
+
+
- substring # end
+
+
+ find last simple
+
+
-
-
- FROM_END
- FROM_END
-
+
+ LAST
+
text
-
-
- 3
-
-
-
-
- 2
+
+
+ an
-
- 78
+
+
+
+ 3
+
+
- substring first-last
+
+
+ find none simple
+
+
-
-
- FIRST
- LAST
-
+
+ FIRST
+
text
+
+
+ Peel
+
+
-
- text
+
+
+
+ -1
+
+
@@ -370,40 +739,49 @@
-
- test find
+
+ get fruit
+ Creates a string for use with the find test.
-
- first find
-
-
- FIRST
-
-
- Banana
-
-
-
-
- an
-
-
+
+ number of calls
+
+
+ 1
-
+
+
+
+
+ Banana
+
+
+
+
+ test find complex
+ Tests the "find" block with a function call.
+
+
+ number of calls
+
- 2
+ 0
- last find
+
+
+ find first complex
+
+
- LAST
+ FIRST
-
- Banana
+
+
@@ -414,159 +792,331 @@
-
- 4
+
+
+
+ 1
+
+
-
- no find
-
-
- FIRST
-
-
- Banana
-
-
-
-
- Peel
-
-
-
-
-
-
- 0
-
-
-
-
-
-
-
-
-
-
- test letter
-
-
- letter #
-
-
-
- FROM_START
-
-
- Blockly
-
-
-
-
- 3
-
-
-
-
-
-
- o
-
-
-
-
- letter # from end
-
-
-
- FROM_END
-
+
+
+
+
+
- Blockly
-
-
-
-
- 3
-
-
-
-
-
-
- k
-
-
-
-
- first letter
-
-
-
- FIRST
-
-
- Blockly
-
-
-
-
-
-
- B
+ find first complex
-
- last letter
-
-
-
- LAST
-
-
- Blockly
-
-
-
-
-
-
- y
+
+ number of calls
+
+
+ 0
-
- random letter
- TRUE
+
+
+
+ find first order complex
+
+
-
-
- POSITIVE
-
-
- FIRST
-
-
- Blockly
+
+ FIRST
+
+
+
+
+ TRUE
-
-
-
- RANDOM
-
-
- Blockly
-
-
+
+
+
+
+
+
+
+
+
+
+ an
+
+
+
+
+ 1
+
+
+
+
+
+
+
+
+
+
+
+ find first order complex
+
+
+
+
+ number of calls
+
+
+ 0
+
+
+
+
+
+
+ find last complex
+
+
+
+
+ LAST
+
+
+
+
+
+
+
+ an
+
+
+
+
+
+
+
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+ find last complex
+
+
+
+
+ number of calls
+
+
+ 0
+
+
+
+
+
+
+ find last order complex
+
+
+
+
+ LAST
+
+
+
+
+ TRUE
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ an
+
+
+
+
+
+
+
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+ find last order complex
+
+
+
+
+ number of calls
+
+
+ 0
+
+
+
+
+
+
+ find none complex
+
+
+
+
+ FIRST
+
+
+
+
+
+
+
+ Peel
+
+
+
+
+
+
+
+
+ -1
+
+
+
+
+
+
+
+
+
+
+
+ find none complex
+
+
+
+
+ number of calls
+
+
+ 0
+
+
+
+
+
+
+ find none order complex
+
+
+
+
+ FIRST
+
+
+
+
+ TRUE
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Peel
+
+
+
+
+
+
+
+
+ -1
+
+
+
+
+
+
+
+
+
+
+
+ find none order complex
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -578,62 +1128,2768 @@
-
- test case
+
+ test get simple
+ Tests the "get letter" block with a variable.
-
- uppercase
-
-
- UPPERCASE
-
-
- Hello World
-
-
-
-
-
+
+ text
+
- HELLO WORLD
+ Blockly
- lowercase
+
+
+ get first simple
+
+
+
+
+
+ FIRST
+
+
+ text
+
+
+
+
+
+
+ B
+
+
+
+
+
+
+ get last simple
+
+
+
+
+
+ LAST
+
+
+ text
+
+
+
+
+
+
+ y
+
+
+
+
+ TRUE
+
+
+ get random simple
+
+
+
+
+ GT
+
+
+ FIRST
+
+
+ text
+
+
+
+
+
+ RANDOM
+
+
+ text
+
+
+
+
+
+
+
+
+
+
+ -1
+
+
+
+
+
+
+
+
+
+
+ get # simple
+
+
+
+
+
+ FROM_START
+
+
+ text
+
+
+
+
+
+
+ 2
+
+
+
+
+
+
+
+
+ o
+
+
+
+
+
+
+ get # order simple
+
+
+
+
+
+ FROM_START
+
+
+ text
+
+
+
+
+
+
+ TRUE
+
+
+
+
+
+
+ 2
+
+
+
+
+
+
+
+
+
+
+
+
+
+ o
+
+
+
+
+
+
+ get #-end simple
+
+
+
+
+
+ FROM_END
+
+
+ text
+
+
+
+
+
+
+ 2
+
+
+
+
+
+
+
+
+ k
+
+
+
+
+
+
+ get #-end order simple
+
+
+
+
+
+ FROM_END
+ The order for index for #-end is addition because this will catch errors in generators where most perform the operation ... - index.
+
+
+ text
+
+
+
+
+ ADD
+
+
+ 0
+
+
+
+
+
+
+ 2
+
+
+
+
+
+
+
+
+
+
+ k
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ get Blockly
+ Creates a string for use with the get test.
+
+
+ number of calls
+
+
+ 1
+
+
+
+
+
+
+ Blockly
+
+
+
+
+ test get complex
+ Tests the "get letter" block with a function call.
+
+
+ text
+
+
+ Blockly
+
+
+
+
+ number of calls
+
+
+ 0
+
+
+
+
+
+
+ get first complex
+
+
+
+
+
+ FIRST
+
+
+
+
+
+
+
+
+
+ B
+
+
+
+
+
+
+
+
+
+ get first complex
+
+
+
+
+ number of calls
+
+
+ 0
+
+
+
+
+
+
+ get first order complex
+
+
+
+
+
+ FIRST
+
+
+
+
+ TRUE
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ B
+
+
+
+
+
+
+
+
+
+ get first order complex
+
+
+
+
+ number of calls
+
+
+ 0
+
+
+
+
+
+
+ get last complex
+
+
+
+
+
+ LAST
+
+
+
+
+
+
+
+
+
+ y
+
+
+
+
+
+
+
+
+
+ get last complex
+
+
+
+
+ number of calls
+
+
+ 0
+
+
+
+
+
+
+ get last order complex
+
+
+
+
+
+ LAST
+
+
+
+
+ TRUE
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ y
+
+
+
+
+
+
+
+
+
+ get last order complex
+
+
+
+
+ number of calls
+
+
+ 0
+
+
+
+
+ TRUE
+
+
+ get random complex
+
+
+
+
+ GT
+
+
+ FIRST
+
+
+ text
+
+
+
+
+
+ RANDOM
+
+
+
+
+
+
+
+
+
+
+
+
+
+ -1
+
+
+
+
+
+
+
+
+
+
+
+
+
+ get random complex
+
+
+
+
+ number of calls
+
+
+ 0
+
+
+
+
+ TRUE
+
+
+ get random order complex
+
+
+
+
+ GT
+
+
+ FIRST
+
+
+ text
+
+
+
+
+
+ RANDOM
+
+
+
+
+ TRUE
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ -1
+
+
+
+
+
+
+
+
+
+
+
+
+
+ get random order complex
+
+
+
+
+ number of calls
+
+
+ 0
+
+
+
+
+
+
+ get # complex
+
+
+
+
+
+ FROM_START
+
+
+
+
+
+
+
+
+
+ 2
+
+
+
+
+
+
+
+
+ o
+
+
+
+
+
+
+
+
+
+ get # complex
+
+
+
+
+ number of calls
+
+
+ 0
+
+
+
+
+
+
+ get # order complex
+
+
+
+
+
+ FROM_START
+
+
+
+
+ TRUE
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ TRUE
+
+
+
+
+
+
+ 2
+
+
+
+
+
+
+
+
+
+
+
+
+
+ o
+
+
+
+
+
+
+
+
+
+ get # order complex
+
+
+
+
+ number of calls
+
+
+ 0
+
+
+
+
+
+
+ get #-end complex
+
+
+
+
+
+ FROM_END
+
+
+
+
+
+
+
+
+
+ 2
+
+
+
+
+
+
+
+
+ k
+
+
+
+
+
+
+
+
+
+ get #-end complex
+
+
+
+
+ number of calls
+
+
+ 0
+
+
+
+
+
+
+ get #-end order complex
+
+
+
+
+
+ FROM_END
+ The order for index for #-end is addition because this will catch errors in generators where most perform the operation ... - index.
+
+
+
+
+ TRUE
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ADD
+
+
+ 0
+
+
+
+
+
+
+ 2
+
+
+
+
+
+
+
+
+
+
+ k
+
+
+
+
+
+
+
+
+
+ get #-end order complex
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ get numbers
+ Creates a string for use with the substring test.
+
+
+ number of calls
+
+
+ 1
+
+
+
+
+
+
+ 123456789
+
+
+
+
+ test substring simple
+ Tests the "get substring" block with a variable.
+
+
+ text
+
+
+ 123456789
+
+
+
+
+
+
+ substring # simple
+
+
+
+
+
+ FROM_START
+ FROM_START
+
+
+ text
+
+
+
+
+
+
+ 1
+
+
+
+
+
+
+
+
+ 2
+
+
+
+
+
+
+
+
+ 23
+
+
+
+
+
+
+ substring # simple order
+
+
+
+
+
+ FROM_START
+ FROM_START
+
+
+ text
+
+
+
+
+
+
+ TRUE
+
+
+
+
+
+
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+ TRUE
+
+
+
+
+
+
+ 2
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 23
+
+
+
+
+
+
+ substring #-end simple
+
+
+
+
+
+ FROM_END
+ FROM_END
+
+
+ text
+
+
+
+
+
+
+ 2
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+
+
+
+
+ 78
+
+
+
+
+
+
+ substring #-end simple order
+
+
+
+
+
+ FROM_END
+ FROM_END
+ The order for index for #-end is addition because this will catch errors in generators where most perform the operation ... - index.
+
+
+ text
+
+
+
+
+ ADD
+
+
+ 0
+
+
+
+
+
+
+ 2
+
+
+
+
+
+
+
+
+ ADD
+
+
+ 0
+
+
+
+
+
+
+ 1
+
+
+
+
+
+
+
+
+
+
+ 78
+
+
+
+
+
+
+ substring first-last simple
+
+
+
+
+
+ FIRST
+ LAST
+
+
+ text
+
+
+
+
+
+
+ text
+
+
+
+
+
+
+ substring # #-end simple
+
+
+
+
+
+ FROM_START
+ FROM_END
+
+
+ text
+
+
+
+
+
+
+ 1
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+
+
+
+
+ 2345678
+
+
+
+
+
+
+ substring #-end # simple
+
+
+
+
+
+ FROM_END
+ FROM_START
+
+
+ text
+
+
+
+
+
+
+ 6
+
+
+
+
+
+
+
+
+ 3
+
+
+
+
+
+
+
+
+ 34
+
+
+
+
+
+
+ substring first # simple
+
+
+
+
+
+ FIRST
+ FROM_START
+
+
+ text
+
+
+
+
+
+
+ 3
+
+
+
+
+
+
+
+
+ 1234
+
+
+
+
+
+
+ substring first #-end simple
+
+
+
+
+
+ FIRST
+ FROM_END
+
+
+ text
+
+
+
+
+
+
+ 1
+
+
+
+
+
+
+
+
+ 12345678
+
+
+
+
+
+
+ substring # last simple
+
+
+
+
+
+ FROM_START
+ LAST
+
+
+ text
+
+
+
+
+
+
+ 6
+
+
+
+
+
+
+
+
+ 789
+
+
+
+
+
+
+ substring #-end last simple
+
+
+
+
+
+ FROM_END
+ LAST
+
+
+ text
+
+
+
+
+
+
+ 2
+
+
+
+
+
+
+
+
+ 789
+
+
+
+
+
+
+ substring all with # #-end simple
+
+
+
+
+
+ FROM_START
+ FROM_END
+
+
+ text
+
+
+
+
+
+
+ 0
+
+
+
+
+
+
+
+
+ 0
+
+
+
+
+
+
+
+
+ 123456789
+
+
+
+
+
+
+ substring all with #-end # simple
+
+
+
+
+
+ FROM_END
+ FROM_START
+
+
+ text
+
+
+
+
+
+
+ 8
+
+
+
+
+
+
+
+
+ 8
+
+
+
+
+
+
+
+
+ 123456789
+
+
+
+
+
+
+ substring all with # #-end math simple
+
+
+
+
+
+ FROM_START
+ FROM_END
+ Checks that the whole string is properly retrieved even if the value for start and end is not a simple number. This is especially important in generators where substring uses [x:length - y] for # #-end.
+
+
+ text
+
+
+
+
+ ADD
+
+
+ 0
+
+
+
+
+
+
+ 0
+
+
+
+
+
+
+
+
+ ADD
+
+
+ 0
+
+
+
+
+
+
+ 0
+
+
+
+
+
+
+
+
+
+
+ 123456789
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ test substring complex
+ Tests the "get substring" block with a function call.
+
+
+ number of calls
+
+
+ 0
+
+
+
+
+
+
+ substring # complex
+
+
+
+
+
+ FROM_START
+ FROM_START
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+
+
+
+
+ 2
+
+
+
+
+
+
+
+
+ 23
+
+
+
+
+
+
+
+
+
+ substring # complex
+
+
+
+
+ number of calls
+
+
+ 0
+
+
+
+
+
+
+ substring # complex order
+
+
+
+
+
+ FROM_START
+ FROM_START
+
+
+
+
+ TRUE
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ TRUE
+
+
+
+
+
+
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+ TRUE
+
+
+
+
+
+
+ 2
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 23
+
+
+
+
+
+
+
+
+
+ substring # complex order
+
+
+
+
+ number of calls
+
+
+ 0
+
+
+
+
+
+
+ substring #-end complex
+
+
+
+
+
+ FROM_END
+ FROM_END
+ The order for index for #-end is addition because this will catch errors in generators where most perform the operation ... - index.
+
+
+
+
+
+
+
+
+
+ 2
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+
+
+
+
+ 78
+
+
+
+
+
+
+
+
+
+ substring #-end complex
+
+
+
+
+ number of calls
+
+
+ 0
+
+
+
+
+
+
+ substring #-end order order
+
+
+
+
+
+ FROM_END
+ FROM_END
+
+
+
+
+ TRUE
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ADD
+
+
+ 0
+
+
+
+
+
+
+ 2
+
+
+
+
+
+
+
+
+ ADD
+
+
+ 0
+
+
+
+
+
+
+ 1
+
+
+
+
+
+
+
+
+
+
+ 78
+
+
+
+
+
+
+
+
+
+ substring #-end order order
+
+
+
+
+ number of calls
+
+
+ 0
+
+
+
+
+
+
+ substring first-last
+
+
+
+
+
+ FIRST
+ LAST
+
+
+
+
+
+
+
+
+
+ text
+
+
+
+
+
+
+
+
+
+ substring first-last
+
+
+
+
+ number of calls
+
+
+ 0
+
+
+
+
+
+
+ substring # #-end complex
+
+
+
+
+
+ FROM_START
+ FROM_END
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+
+
+
+
+ 2345678
+
+
+
+
+
+
+
+
+
+ substring # #-end complex
+
+
+
+
+ number of calls
+
+
+ 0
+
+
+
+
+
+
+ substring #-end # complex
+
+
+
+
+
+ FROM_END
+ FROM_START
+
+
+
+
+
+
+
+
+
+ 6
+
+
+
+
+
+
+
+
+ 3
+
+
+
+
+
+
+
+
+ 34
+
+
+
+
+
+
+
+
+
+ substring #-end # complex
+
+
+
+
+ number of calls
+
+
+ 0
+
+
+
+
+
+
+ substring first # complex
+
+
+
+
+
+ FIRST
+ FROM_START
+
+
+
+
+
+
+
+
+
+ 3
+
+
+
+
+
+
+
+
+ 1234
+
+
+
+
+
+
+
+
+
+ substring first # complex
+
+
+
+
+ number of calls
+
+
+ 0
+
+
+
+
+
+
+ substring first #-end complex
+
+
+
+
+
+ FIRST
+ FROM_END
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+
+
+
+
+ 12345678
+
+
+
+
+
+
+
+
+
+ substring first #-end complex
+
+
+
+
+ number of calls
+
+
+ 0
+
+
+
+
+
+
+ substring # last complex
+
+
+
+
+
+ FROM_START
+ LAST
+
+
+
+
+
+
+
+
+
+ 6
+
+
+
+
+
+
+
+
+ 789
+
+
+
+
+
+
+
+
+
+ substring # last complex
+
+
+
+
+ number of calls
+
+
+ 0
+
+
+
+
+
+
+ substring #-end last complex
+
+
+
+
+
+ FROM_END
+ LAST
+
+
+
+
+
+
+
+
+
+ 2
+
+
+
+
+
+
+
+
+ 789
+
+
+
+
+
+
+
+
+
+ substring #-end last complex
+
+
+
+
+ number of calls
+
+
+ 0
+
+
+
+
+
+
+ substring all with # #-end complex
+
+
+
+
+
+ FROM_START
+ FROM_END
+
+
+
+
+
+
+
+
+
+ 0
+
+
+
+
+
+
+
+
+ 0
+
+
+
+
+
+
+
+
+ 123456789
+
+
+
+
+
+
+
+
+
+ substring all with # #-end complex
+
+
+
+
+ number of calls
+
+
+ 0
+
+
+
+
+
+
+ substring all with #-end # complex
+
+
+
+
+
+ FROM_END
+ FROM_START
+
+
+
+
+
+
+
+
+
+ 8
+
+
+
+
+
+
+
+
+ 8
+
+
+
+
+
+
+
+
+ 123456789
+
+
+
+
+
+
+
+
+
+ substring all with #-end # complex
+
+
+
+
+ number of calls
+
+
+ 0
+
+
+
+
+
+
+ substring all with # #-end math complex
+
+
+
+
+
+ FROM_START
+ FROM_END
+ Checks that the whole string is properly retrieved even if the value for start and end is not a simple number. This is especially important in generators where substring uses [x:length - y] for # #-end.
+
+
+
+
+
+
+
+ ADD
+
+
+ 0
+
+
+
+
+
+
+ 0
+
+
+
+
+
+
+
+
+ ADD
+
+
+ 0
+
+
+
+
+
+
+ 0
+
+
+
+
+
+
+
+
+
+
+ 123456789
+
+
+
+
+
+
+
+
+
+ substring all with # #-end math complex
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ test case
+ Tests the "change casing" block.
+
+
+ text
+
+
+ Hello World
+
+
+
+
+
+
+ uppercase
+
+
- LOWERCASE
+ UPPERCASE
-
- Hello World
+
+ text
- hello world
+ HELLO WORLD
- titlecase
+
+
+ uppercase order
+
+
- TITLECASE
+ UPPERCASE
-
- heLLo WorlD
+
+
+
+ TRUE
+
+
+
+
+ text
+
+
+
+
+
- Hello World
+ HELLO WORLD
+
+
+ text
+
+
+ Hello World
+
+
+
+
+
+
+ lowercase
+
+
+
+
+ LOWERCASE
+
+
+ text
+
+
+
+
+
+
+ hello world
+
+
+
+
+
+
+ lowercase order
+
+
+
+
+ LOWERCASE
+
+
+
+
+ TRUE
+
+
+
+
+ text
+
+
+
+
+
+
+
+
+
+
+
+ hello world
+
+
+
+
+ text
+
+
+ heLLo WorlD
+
+
+
+
+
+
+ titlecase
+
+
+
+
+ TITLECASE
+
+
+ text
+
+
+
+
+
+
+ Hello World
+
+
+
+
+
+
+ titlecase order
+
+
+
+
+ TITLECASE
+
+
+
+
+ TRUE
+
+
+
+
+ text
+
+
+
+
+
+
+
+
+
+
+
+ Hello World
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -641,62 +3897,193 @@
-
+
test trim
+ Tests the "trim" block.
-
- trim both
-
-
- BOTH
-
-
- abc def
-
-
-
-
-
+
+ text
+
- abc def
+ abc def
- trim left
+
+
+ trim both
+
+
- LEFT
+ BOTH
-
- abc def
+
+ text
- abc def
+ abc def
- trim right
+
+
+ trim both order
+
+
- RIGHT
+ BOTH
-
- abc def
+
+
+
+ TRUE
+
+
+
+
+ text
+
+
+
+
+
- abc def
+ abc def
+
+
+
+
+ trim left
+
+
+
+
+ LEFT
+
+
+ text
+
+
+
+
+
+
+ abc def
+
+
+
+
+
+
+ trim left order
+
+
+
+
+ LEFT
+
+
+
+
+ TRUE
+
+
+
+
+ text
+
+
+
+
+
+
+
+
+
+
+
+ abc def
+
+
+
+
+
+
+ trim right
+
+
+
+
+ RIGHT
+
+
+ text
+
+
+
+
+
+
+ abc def
+
+
+
+
+
+
+ trim right order
+
+
+
+
+ RIGHT
+
+
+
+
+ TRUE
+
+
+
+
+ text
+
+
+
+
+
+
+
+
+
+
+
+ abc def
+
+
+
+
+
+
+
+
+
+
@@ -704,4 +4091,4 @@
-
+
\ No newline at end of file
diff --git a/tests/generators/unittest.js b/tests/generators/unittest.js
index 560e6b91f..d2b94e66d 100644
--- a/tests/generators/unittest.js
+++ b/tests/generators/unittest.js
@@ -45,11 +45,12 @@ Blockly.Blocks['unittest_assertequals'] = {
this.setColour(65);
this.setPreviousStatement(true);
this.setNextStatement(true);
- this.appendDummyInput()
- .appendField(new Blockly.FieldTextInput('test name'), 'MESSAGE');
- this.appendValueInput('ACTUAL', null)
+ this.appendValueInput('MESSAGE')
+ .appendField('name')
+ .setCheck('String');
+ this.appendValueInput('ACTUAL')
.appendField('actual');
- this.appendValueInput('EXPECTED', null)
+ this.appendValueInput('EXPECTED')
.appendField('expected');
this.setTooltip('Tests that "actual == expected".');
},
@@ -64,9 +65,10 @@ Blockly.Blocks['unittest_assertvalue'] = {
this.setColour(65);
this.setPreviousStatement(true);
this.setNextStatement(true);
- this.appendDummyInput()
- .appendField(new Blockly.FieldTextInput('test name'), 'MESSAGE');
- this.appendValueInput('ACTUAL', Boolean)
+ this.appendValueInput('MESSAGE', 'test name')
+ .appendField('name')
+ .setCheck('String');
+ this.appendValueInput('ACTUAL')
.appendField('assert')
.appendField(new Blockly.FieldDropdown(
[['true', 'TRUE'], ['false', 'FALSE'], ['null', 'NULL']]), 'EXPECTED');
@@ -92,3 +94,24 @@ Blockly.Blocks['unittest_fail'] = {
return ['unittestResults'];
}
};
+
+Blockly.Blocks['unittest_adjustindex'] = {
+ // Adjusts the indexing based on current setting.
+ init: function() {
+ this.jsonInit({
+ "message0": "adjusted %1",
+ "args0": [
+ {
+ "type": "input_value",
+ "name": "INDEX",
+ "check": "Number"
+ }
+ ],
+ "inputsInline": true,
+ "output": "Number",
+ "colour": 65,
+ "tooltip": "Adjusts the value based on whether generated code is using " +
+ "zero or one based indexing"
+ });
+ }
+};
diff --git a/tests/generators/unittest_dart.js b/tests/generators/unittest_dart.js
index 280595fc3..f1334c993 100644
--- a/tests/generators/unittest_dart.js
+++ b/tests/generators/unittest_dart.js
@@ -111,7 +111,8 @@ Blockly.Dart['unittest_main'].defineAssert_ = function() {
Blockly.Dart['unittest_assertequals'] = function(block) {
// Asserts that a value equals another value.
- var message = Blockly.Dart.quote_(block.getFieldValue('MESSAGE'));
+ var message = Blockly.Dart.valueToCode(block, 'MESSAGE',
+ Blockly.Dart.ORDER_NONE) || '';
var actual = Blockly.Dart.valueToCode(block, 'ACTUAL',
Blockly.Dart.ORDER_NONE) || 'null';
var expected = Blockly.Dart.valueToCode(block, 'EXPECTED',
@@ -122,7 +123,8 @@ Blockly.Dart['unittest_assertequals'] = function(block) {
Blockly.Dart['unittest_assertvalue'] = function(block) {
// Asserts that a value is true, false, or null.
- var message = Blockly.Dart.quote_(block.getFieldValue('MESSAGE'));
+ var message = Blockly.Dart.valueToCode(block, 'MESSAGE',
+ Blockly.Dart.ORDER_NONE) || '';
var actual = Blockly.Dart.valueToCode(block, 'ACTUAL',
Blockly.Dart.ORDER_NONE) || 'null';
var expected = block.getFieldValue('EXPECTED');
@@ -141,7 +143,8 @@ Blockly.Dart['unittest_fail'] = function(block) {
// Always assert an error.
var resultsVar = Blockly.Dart.variableDB_.getName('unittestResults',
Blockly.Variables.NAME_TYPE);
- var message = Blockly.Dart.quote_(block.getFieldValue('MESSAGE'));
+ var message = Blockly.Dart.valueToCode(block, 'MESSAGE',
+ Blockly.Dart.ORDER_NONE) || '';
var functionName = Blockly.Dart.provideFunction_(
'unittest_fail',
[ 'void ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ +
@@ -154,3 +157,21 @@ Blockly.Dart['unittest_fail'] = function(block) {
'}']);
return functionName + '(' + message + ');\n';
};
+
+Blockly.Dart['unittest_adjustindex'] = function(block) {
+ var index = Blockly.Dart.valueToCode(block, 'INDEX',
+ Blockly.Dart.ORDER_ADDITIVE) || '0';
+ // Adjust index if using one-based indexing.
+ if (Blockly.Dart.ONE_BASED_INDEXING) {
+ if (Blockly.isNumber(index)) {
+ // If the index is a naked number, adjust it right now.
+ return [parseFloat(index) + 1, Blockly.Dart.ORDER_ATOMIC];
+ } else {
+ // If the index is dynamic, adjust it in code.
+ index = index + ' + 1';
+ }
+ } else if (Blockly.isNumber(index)) {
+ return [index, Blockly.Dart.ORDER_ATOMIC];
+ }
+ return [index, Blockly.Dart.ORDER_ADDITIVE];
+};
diff --git a/tests/generators/unittest_javascript.js b/tests/generators/unittest_javascript.js
index ed5415c0b..991568614 100644
--- a/tests/generators/unittest_javascript.js
+++ b/tests/generators/unittest_javascript.js
@@ -35,15 +35,15 @@ Blockly.JavaScript['unittest_main'] = function(block) {
' var report = [];',
' var summary = [];',
' var fails = 0;',
- ' for (var x = 0; x < ' + resultsVar + '.length; x++) {',
- ' if (' + resultsVar + '[x][0]) {',
+ ' for (var i = 0; i < ' + resultsVar + '.length; i++) {',
+ ' if (' + resultsVar + '[i][0]) {',
' summary.push(".");',
' } else {',
' summary.push("F");',
' fails++;',
' report.push("");',
- ' report.push("FAIL: " + ' + resultsVar + '[x][2]);',
- ' report.push(' + resultsVar + '[x][1]);',
+ ' report.push("FAIL: " + ' + resultsVar + '[i][2]);',
+ ' report.push(' + resultsVar + '[i][1]);',
' }',
' }',
' report.unshift(summary.join(""));',
@@ -115,7 +115,8 @@ Blockly.JavaScript['unittest_main'].defineAssert_ = function(block) {
Blockly.JavaScript['unittest_assertequals'] = function(block) {
// Asserts that a value equals another value.
- var message = Blockly.JavaScript.quote_(block.getFieldValue('MESSAGE'));
+ var message = Blockly.JavaScript.valueToCode(block, 'MESSAGE',
+ Blockly.JavaScript.ORDER_NONE) || '';
var actual = Blockly.JavaScript.valueToCode(block, 'ACTUAL',
Blockly.JavaScript.ORDER_COMMA) || 'null';
var expected = Blockly.JavaScript.valueToCode(block, 'EXPECTED',
@@ -126,7 +127,8 @@ Blockly.JavaScript['unittest_assertequals'] = function(block) {
Blockly.JavaScript['unittest_assertvalue'] = function(block) {
// Asserts that a value is true, false, or null.
- var message = Blockly.JavaScript.quote_(block.getFieldValue('MESSAGE'));
+ var message = Blockly.JavaScript.valueToCode(block, 'MESSAGE',
+ Blockly.JavaScript.ORDER_NONE) || '';
var actual = Blockly.JavaScript.valueToCode(block, 'ACTUAL',
Blockly.JavaScript.ORDER_COMMA) || 'null';
var expected = block.getFieldValue('EXPECTED');
@@ -145,7 +147,8 @@ Blockly.JavaScript['unittest_fail'] = function(block) {
// Always assert an error.
var resultsVar = Blockly.JavaScript.variableDB_.getName('unittestResults',
Blockly.Variables.NAME_TYPE);
- var message = Blockly.JavaScript.quote_(block.getFieldValue('MESSAGE'));
+ var message = Blockly.JavaScript.valueToCode(block, 'MESSAGE',
+ Blockly.JavaScript.ORDER_NONE) || '';
var functionName = Blockly.JavaScript.provideFunction_(
'unittest_fail',
[ 'function ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ +
@@ -158,3 +161,21 @@ Blockly.JavaScript['unittest_fail'] = function(block) {
'}']);
return functionName + '(' + message + ');\n';
};
+
+Blockly.JavaScript['unittest_adjustindex'] = function(block) {
+ var index = Blockly.JavaScript.valueToCode(block, 'INDEX',
+ Blockly.JavaScript.ORDER_ADDITION) || '0';
+ // Adjust index if using one-based indexing.
+ if (Blockly.JavaScript.ONE_BASED_INDEXING) {
+ if (Blockly.isNumber(index)) {
+ // If the index is a naked number, adjust it right now.
+ return [parseFloat(index) + 1, Blockly.JavaScript.ORDER_ATOMIC];
+ } else {
+ // If the index is dynamic, adjust it in code.
+ index = index + ' + 1';
+ }
+ } else if (Blockly.isNumber(index)) {
+ return [index, Blockly.JavaScript.ORDER_ATOMIC];
+ }
+ return [index, Blockly.JavaScript.ORDER_ADDITION];
+};
diff --git a/tests/generators/unittest_lua.js b/tests/generators/unittest_lua.js
index 75261f0a2..d687b091b 100644
--- a/tests/generators/unittest_lua.js
+++ b/tests/generators/unittest_lua.js
@@ -105,13 +105,15 @@ Blockly.Lua['unittest_main'].defineAssert_ = function(block) {
' actual = "{" .. table.concat(actual, ", ") .. "}"',
' end',
' end',
- ' if actual == expected then',
+ ' if actual == expected or (type(actual) == "number" and ' +
+ 'type(expected) == "number" and math.abs(actual - expected) < ' +
+ '1e-9) then ',
' table.insert(' + resultsVar +
', {success=true, log="OK", title=message})',
' else',
' table.insert(' + resultsVar + ', {success=false, ' +
'log=string.format("Expected: %s\\nActual: %s"' +
- ', expected, actual), title=message})',
+ ', tostring(expected), tostring(actual)), title=message})',
' end',
'end']);
return functionName;
@@ -119,7 +121,8 @@ Blockly.Lua['unittest_main'].defineAssert_ = function(block) {
Blockly.Lua['unittest_assertequals'] = function(block) {
// Asserts that a value equals another value.
- var message = Blockly.Lua.quote_(block.getFieldValue('MESSAGE'));
+ var message = Blockly.Lua.valueToCode(block, 'MESSAGE',
+ Blockly.Lua.ORDER_NONE) || '';
var actual = Blockly.Lua.valueToCode(block, 'ACTUAL',
Blockly.Lua.ORDER_NONE) || 'nil';
var expected = Blockly.Lua.valueToCode(block, 'EXPECTED',
@@ -130,7 +133,8 @@ Blockly.Lua['unittest_assertequals'] = function(block) {
Blockly.Lua['unittest_assertvalue'] = function(block) {
// Asserts that a value is true, false, or null.
- var message = Blockly.Lua.quote_(block.getFieldValue('MESSAGE'));
+ var message = Blockly.Lua.valueToCode(block, 'MESSAGE',
+ Blockly.Lua.ORDER_NONE) || '';
var actual = Blockly.Lua.valueToCode(block, 'ACTUAL',
Blockly.Lua.ORDER_NONE) || 'nil';
var expected = block.getFieldValue('EXPECTED');
@@ -149,7 +153,8 @@ Blockly.Lua['unittest_fail'] = function(block) {
// Always assert an error.
var resultsVar = Blockly.Lua.variableDB_.getName('unittestResults',
Blockly.Variables.NAME_TYPE);
- var message = Blockly.Lua.quote_(block.getFieldValue('MESSAGE'));
+ var message = Blockly.Lua.valueToCode(block, 'MESSAGE',
+ Blockly.Lua.ORDER_NONE) || '';
var functionName = Blockly.Lua.provideFunction_(
'unittest_fail',
['function ' + Blockly.Lua.FUNCTION_NAME_PLACEHOLDER_ + '(message)',
@@ -161,3 +166,14 @@ Blockly.Lua['unittest_fail'] = function(block) {
'end']);
return functionName + '(' + message + ')\n';
};
+
+Blockly.Lua['unittest_adjustindex'] = function(block) {
+ var index = Blockly.Lua.valueToCode(block, 'INDEX',
+ Blockly.Lua.ORDER_ADDITIVE) || '0';
+ if (Blockly.isNumber(index)) {
+ // If the index is a naked number, adjust it right now.
+ return [parseFloat(index) + 1, Blockly.Lua.ORDER_ATOMIC];
+ }
+ // If the index is dynamic, adjust it in code.
+ return [index + ' + 1', Blockly.Lua.ORDER_ATOMIC];
+};
diff --git a/tests/generators/unittest_php.js b/tests/generators/unittest_php.js
index 429831ae9..3a80502ba 100644
--- a/tests/generators/unittest_php.js
+++ b/tests/generators/unittest_php.js
@@ -78,45 +78,50 @@ Blockly.PHP['unittest_main'].defineAssert_ = function(block) {
Blockly.Variables.NAME_TYPE);
var functionName = Blockly.PHP.provideFunction_(
'assertEquals',
- [ ' function equals($a, $b) {',
- ' if ($a === $b) {',
- ' return true;',
- ' } else if ((is_numeric($a)) && (is_numeric($b)) &&',
- ' (round($a,15) == round($b,15))) {',
- ' return true;',
- ' } else if (is_array($a) && is_array($b)) {',
- ' if (count($a) != count($b)) {',
- ' return false;',
- ' }',
- ' for ($i = 0; $i < count($a); $i++) {',
- ' if (!equals($a[$i], $b[$i])) {',
- ' return false;',
- ' }',
- ' }',
- ' return true;',
- ' }',
- ' return false;',
- ' }',
- 'function ' + Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_ +
- '($actual, $expected, $message) {',
- 'global ' + resultsVar + ';',
- ' // Asserts that a value equals another value.',
- ' if (!is_array(' + resultsVar + ')) {',
- ' throw new Exception("Orphaned assert: " . $message);',
- ' }',
- ' if (equals($actual, $expected)) {',
- ' array_push(' + resultsVar + ', [true, "OK", $message]);',
- ' } else {',
- ' array_push(' + resultsVar + ', [false, ' +
- '"Expected: " . $expected . "\\nActual: " . $actual, $message]);',
- ' }',
- '}']);
+ [' function equals($a, $b) {',
+ ' if ($a === $b) {',
+ ' return true;',
+ ' } else if ((is_numeric($a)) && (is_numeric($b)) &&',
+ ' (round($a,15) == round($b,15))) {',
+ ' return true;',
+ ' } else if (is_array($a) && is_array($b)) {',
+ ' if (count($a) != count($b)) {',
+ ' return false;',
+ ' }',
+ ' for ($i = 0; $i < count($a); $i++) {',
+ ' if (!equals($a[$i], $b[$i])) {',
+ ' return false;',
+ ' }',
+ ' }',
+ ' return true;',
+ ' }',
+ ' return false;',
+ ' }',
+ 'function ' + Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_ +
+ '($actual, $expected, $message) {',
+ 'global ' + resultsVar + ';',
+ ' // Asserts that a value equals another value.',
+ ' if (!is_array(' + resultsVar + ')) {',
+ ' throw new Exception("Orphaned assert: " . $message);',
+ ' }',
+ ' if (equals($actual, $expected)) {',
+ ' array_push(' + resultsVar + ', [true, "OK", $message]);',
+ ' } else {',
+ ' $expected = is_array($expected) ? implode(" ", $expected) : ' +
+ '$expected;',
+ ' $actual = is_array($actual) ? implode(" ", $actual) : ' +
+ '$actual;',
+ ' array_push(' + resultsVar + ', [false, ' +
+ '"Expected: " . $expected . "\\nActual: " . $actual, $message]);',
+ ' }',
+ '}']);
return functionName;
};
Blockly.PHP['unittest_assertequals'] = function(block) {
// Asserts that a value equals another value.
- var message = Blockly.PHP.quote_(block.getFieldValue('MESSAGE'));
+ var message = Blockly.PHP.valueToCode(block, 'MESSAGE',
+ Blockly.PHP.ORDER_NONE) || '';
var actual = Blockly.PHP.valueToCode(block, 'ACTUAL',
Blockly.PHP.ORDER_COMMA) || 'null';
var expected = Blockly.PHP.valueToCode(block, 'EXPECTED',
@@ -127,7 +132,8 @@ Blockly.PHP['unittest_assertequals'] = function(block) {
Blockly.PHP['unittest_assertvalue'] = function(block) {
// Asserts that a value is true, false, or null.
- var message = Blockly.PHP.quote_(block.getFieldValue('MESSAGE'));
+ var message = Blockly.PHP.valueToCode(block, 'MESSAGE',
+ Blockly.PHP.ORDER_NONE) || '';
var actual = Blockly.PHP.valueToCode(block, 'ACTUAL',
Blockly.PHP.ORDER_COMMA) || 'null';
var expected = block.getFieldValue('EXPECTED');
@@ -146,7 +152,8 @@ Blockly.PHP['unittest_fail'] = function(block) {
// Always assert an error.
var resultsVar = Blockly.PHP.variableDB_.getName('unittestResults',
Blockly.Variables.NAME_TYPE);
- var message = Blockly.PHP.quote_(block.getFieldValue('MESSAGE'));
+ var message = Blockly.PHP.valueToCode(block, 'MESSAGE',
+ Blockly.PHP.ORDER_NONE) || '';
var functionName = Blockly.PHP.provideFunction_(
'unittest_fail',
[ 'function ' + Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_ +
@@ -160,3 +167,21 @@ Blockly.PHP['unittest_fail'] = function(block) {
'}']);
return functionName + '(' + message + ');\n';
};
+
+Blockly.PHP['unittest_adjustindex'] = function(block) {
+ var index = Blockly.PHP.valueToCode(block, 'INDEX',
+ Blockly.PHP.ORDER_ADDITION) || '0';
+ // Adjust index if using one-based indexing.
+ if (Blockly.PHP.ONE_BASED_INDEXING) {
+ if (Blockly.isNumber(index)) {
+ // If the index is a naked number, adjust it right now.
+ return [parseFloat(index) + 1, Blockly.PHP.ORDER_ATOMIC];
+ } else {
+ // If the index is dynamic, adjust it in code.
+ index = index + ' + 1';
+ }
+ } else if (Blockly.isNumber(index)) {
+ return [index, Blockly.PHP.ORDER_ATOMIC];
+ }
+ return [index, Blockly.PHP.ORDER_ADDITION];
+};
diff --git a/tests/generators/unittest_python.js b/tests/generators/unittest_python.js
index fc64d6efc..2b459aa30 100644
--- a/tests/generators/unittest_python.js
+++ b/tests/generators/unittest_python.js
@@ -89,7 +89,8 @@ Blockly.Python['unittest_main'].defineAssert_ = function() {
Blockly.Python['unittest_assertequals'] = function(block) {
// Asserts that a value equals another value.
- var message = Blockly.Python.quote_(block.getFieldValue('MESSAGE'));
+ var message = Blockly.Python.valueToCode(block, 'MESSAGE',
+ Blockly.Python.ORDER_NONE) || '';
var actual = Blockly.Python.valueToCode(block, 'ACTUAL',
Blockly.Python.ORDER_NONE) || 'None';
var expected = Blockly.Python.valueToCode(block, 'EXPECTED',
@@ -100,7 +101,8 @@ Blockly.Python['unittest_assertequals'] = function(block) {
Blockly.Python['unittest_assertvalue'] = function(block) {
// Asserts that a value is true, false, or null.
- var message = Blockly.Python.quote_(block.getFieldValue('MESSAGE'));
+ var message = Blockly.Python.valueToCode(block, 'MESSAGE',
+ Blockly.Python.ORDER_NONE) || '';
var actual = Blockly.Python.valueToCode(block, 'ACTUAL',
Blockly.Python.ORDER_NONE) || 'None';
var expected = block.getFieldValue('EXPECTED');
@@ -119,7 +121,8 @@ Blockly.Python['unittest_fail'] = function(block) {
// Always assert an error.
var resultsVar = Blockly.Python.variableDB_.getName('unittestResults',
Blockly.Variables.NAME_TYPE);
- var message = Blockly.Python.quote_(block.getFieldValue('MESSAGE'));
+ var message = Blockly.Python.valueToCode(block, 'MESSAGE',
+ Blockly.Python.ORDER_NONE) || '';
var functionName = Blockly.Python.provideFunction_(
'fail',
['def ' + Blockly.Python.FUNCTION_NAME_PLACEHOLDER_ + '(message):',
@@ -129,3 +132,21 @@ Blockly.Python['unittest_fail'] = function(block) {
' ' + resultsVar + '.append((False, "Fail.", message))']);
return functionName + '(' + message + ')\n';
};
+
+Blockly.Python['unittest_adjustindex'] = function(block) {
+ var index = Blockly.Python.valueToCode(block, 'INDEX',
+ Blockly.Python.ORDER_ADDITIVE) || '0';
+ // Adjust index if using one-based indexing.
+ if (Blockly.Python.ONE_BASED_INDEXING) {
+ if (Blockly.isNumber(index)) {
+ // If the index is a naked number, adjust it right now.
+ return [parseFloat(index) + 1, Blockly.Python.ORDER_ATOMIC];
+ } else {
+ // If the index is dynamic, adjust it in code.
+ index = index + ' + 1';
+ }
+ } else if (Blockly.isNumber(index)) {
+ return [index, Blockly.Python.ORDER_ATOMIC];
+ }
+ return [index, Blockly.Python.ORDER_ADDITIVE];
+};
diff --git a/tests/generators/variables.xml b/tests/generators/variables.xml
index 544d897d0..a11d0a01a 100644
--- a/tests/generators/variables.xml
+++ b/tests/generators/variables.xml
@@ -10,7 +10,11 @@
- variable
+
+
+ variable
+
+
item
@@ -31,7 +35,11 @@
- reserved variable
+
+
+ reserved variable
+
+
if
diff --git a/tests/jsunit/connection_db_test.js b/tests/jsunit/connection_db_test.js
index 269d2d123..558edf100 100644
--- a/tests/jsunit/connection_db_test.js
+++ b/tests/jsunit/connection_db_test.js
@@ -22,8 +22,8 @@
function verify_DB_(msg, expected, db) {
var equal = (expected.length == db.length);
if (equal) {
- for (var x = 0; x < expected.length; x++) {
- if (expected[x] != db[x]) {
+ for (var i = 0; i < expected.length; i++) {
+ if (expected[i] != db[i]) {
equal = false;
break;
}