From 2b191e897e1b6f09133c03a4fd2bd7febd677ee6 Mon Sep 17 00:00:00 2001
From: Monica Kozbial
Date: Fri, 8 Jul 2016 11:43:48 -0700
Subject: [PATCH] Adding indexing settings, tests and fixing bugs (#464)
* Add indexing setting for JavaScript Generation
Adding setting to allow for switching between zero and one based indexing for Blockly Blocks such that the generated code will use this flag to determine whether one based or zero based indexing should be used. One based indexing is enabled by default.
* Updating js lists to do zero and one based index
Updated generated JavaScript to change depending on whether one based indexing is enabled or not.
* Updating js text to do zero and one based index
Change so that JavaScript generated for text blocks either assumes blocks use zero or one based index based on setting.
* Start of python indexing
Start of work on allowing one and zero indexing for generated python for lists.
* Fixing bug and lint fixed
Fixing bug caused by not setting the return of concat when concatenating lines for sublist and substring functions. Also renamed these functions to be getSubsequece. Fixed lint errors with spacing
* Converting from if to switch statements
Comverting if statements to switch statements when appropriate and adding spacing.
* Modified sublist JavaScript generation
Added case so that helper function is not generated if not necessary. Helper function is not generated if list length is not needed or if list is a simple block (such as a variable, as oppossed to a function call or list create).
* Stripping unecessary ids
Removing ids from xml file.
* Localisation updates from https://translatewiki.net.
* Fix typo in flyout.js (#403)
* Fix typo in flyout.js (#402)
* Localisation updates from https://translatewiki.net.
* Add indexing setting for JavaScript Generation
Adding setting to allow for switching between zero and one based indexing for Blockly Blocks such that the generated code will use this flag to determine whether one based or zero based indexing should be used. One based indexing is enabled by default.
* Updating js lists to do zero and one based index
Updated generated JavaScript to change depending on whether one based indexing is enabled or not.
* Updating js text to do zero and one based index
Change so that JavaScript generated for text blocks either assumes blocks use zero or one based index based on setting.
* Fixing bug and lint fixed
Fixing bug caused by not setting the return of concat when concatenating lines for sublist and substring functions. Also renamed these functions to be getSubsequece. Fixed lint errors with spacing
* Converting from if to switch statements
Comverting if statements to switch statements when appropriate and adding spacing.
* Modified sublist JavaScript generation
Added case so that helper function is not generated if not necessary. Helper function is not generated if list length is not needed or if list is a simple block (such as a variable, as oppossed to a function call or list create).
* Stripping unecessary ids
Removing ids from xml file.
* Updating generator test
Modifying sublist test and re-formatting spacing between blocks.
* Updating js lists to do zero and one based index
Updated generated JavaScript to change depending on whether one based indexing is enabled or not.
* Updating js text to do zero and one based index
Change so that JavaScript generated for text blocks either assumes blocks use zero or one based index based on setting.
* Fixing bug and lint fixed
Fixing bug caused by not setting the return of concat when concatenating lines for sublist and substring functions. Also renamed these functions to be getSubsequece. Fixed lint errors with spacing
* Converting from if to switch statements
Comverting if statements to switch statements when appropriate and adding spacing.
* Modified sublist JavaScript generation
Added case so that helper function is not generated if not necessary. Helper function is not generated if list length is not needed or if list is a simple block (such as a variable, as oppossed to a function call or list create).
* Stripping unecessary ids
Removing ids from xml file.
* Localisation updates from https://translatewiki.net.
* Localisation updates from https://translatewiki.net.
* Updating js lists to do zero and one based index
Updated generated JavaScript to change depending on whether one based indexing is enabled or not.
* Fixing bug and lint fixed
Fixing bug caused by not setting the return of concat when concatenating lines for sublist and substring functions. Also renamed these functions to be getSubsequece. Fixed lint errors with spacing
* Modified sublist JavaScript generation
Added case so that helper function is not generated if not necessary. Helper function is not generated if list length is not needed or if list is a simple block (such as a variable, as oppossed to a function call or list create).
* Stripping unecessary ids
Removing ids from xml file.
* Updating generator test
Modifying sublist test and re-formatting spacing between blocks.
* Adding tests for indexing and extra cases
Adding tests for indexing with custom block to adjust number based on what indexing is being generated.
* Adding tests and renaming tests
Adding tests for sublist and renaming tests.
* Fixes for order for sublists
Fixes so that parenthesis are generated properly for index for sublist
* Cleaning up test generated code
Changing order returned for unit test adjust index function to generate less unecessary parenthesis.
* Adding tests for order
Adding tests for order, relevant for methods that use index from start (because 1 is added)
* Fixing JS order for getIndex and setIndex
Changing to the correct order type when calling valueToCode in JS generation for getIndex and setIndex.
* Fixed unittest adjustIndex
Fixed uninttest adjustindex to also check whether the ONE_BASED_INDEXING variable has been defined to ensure proper behaviour.
* Fixing lint and formatting for JS/lists
Making line fixes and changing an if/elseif to case statement.
* Tests added to include case for bug found
Added tests with sublist combinations of different where's for the two indices after bug for this found in python.
* Adding and renaming tests
Adding test case for creating a sublist that encompasses the whole list but uses # and #-end instead of first last (applicable for python). Also, renaming tests.
* Adding contant and fixing python lists bugs
Adding contant for ONE_BASED_INDEXING and fixing bugs in python for lists.
* Fixing test get random
Fixing test get random to take into account indexing for return value.
* Adding indexing checkbox to test page
Adding checkbos on test page so that code can be generated for one and zero based indexing. Languages that are generated with zero based indexing that do not have it implemented will fail tests as expected.
* Fixing unittest getremove random
Fixing unittest getremove random to take into account the return value based on indexing.
* Change comparison for getremove random test
Fixed comparison to equal for the return value for getremove random.
* Fixing bugs with lists zero-indexing
Fixing getIndex and getSublist methods to pass for zero-indexed tests.
* Adding test cases and formatting
Adding test cases to text tests, reordering a couple list test, and formatting block spacing.
* Fixing unittest expected value
Fixing expected value fore unit tests for sublist.
* Cleanup
Removing obvious comments, formatting fixes, and naming in generated code in JS.
* Helper function for Python lists
Adding helper function for casting to int for indices.
* Expanding helper to reduce duplicated code
Expanding helper method to also get the property with the correct order and check indexing to reduce duplicated code.
* Cleaning up JS indexing with helper function
Adding helper function for indexing and used it in lists and text.
* Moving helper function and formatting fixes
Moving helper function, formatting fixes, and changing some generated code variable names.
* Fixing python generation for text
Fixing all failinng tests for python and using new helper method.
* Lint fixes and order in indexOf
Making lint fixes and correcting returned order in indexOf.
* Python variable renaming
Renaming a few generated variables.
* Fixing comment and order
Fixing comment to list Blockly.Block type and fixing order because it could be higher.
* Switching back to if
Switching switch back to if statements because there weren't enough cases to warrant for a switch.
* Adding order and fixing lists for Dart
Adding if null operator to operator precedence for Dart. Also, fixing lists implementation to pass unit tests and adding zero-indexing functionality.
* Formatting and lint fixes
Formatting and lint fixes
* Dart text fixed
Fixing Dart text generation to pass unit tests.
* Changing back to variable
Changing switch condition back to variable.
* Fixing ORDER_OVERRIDES
Inner and outer order was switched .
* Adding bug with order caused by generator change
Flooring order before comparision because of how the order constants were modified.
* Adding list tests
Adding tests for additional cases for lists/
* Adding comment for dart order
Adding comment for Dart ORDER_IF_NULL operator.
* Formatting fixes
Formatting fixes for line indentation.
* Fixing PHP order and lists generation
Fixing PHP order constants and fixing lists so that they pass unit tests.
* Fixing tests
Removing duplicate unit test
* Adding text tests
Adding tests for text.
* Renaming variable and removing unused variable
Renaming variables from exceptionIndex to errorIndex and removing unused at variable.
* Adding missing function call to test
Adding missing funciton call to test that was causing tests to fail when they shouldn't.
* Fixing PHP text generation
Fixing PHP text code generation so it passes unit tests.
* Formatting fixes
Cleaning up code, renamiing a variable.
* Fixing failing subsequence tests
Fixing JS code that failed for sublist/substring tests.
* Fixing intentation
Fixing indentation.
* Fixing Dart sublist/substring
Fixing sublist/substring to include condiiton where FROM_START (and not throw error by mistake) when zero-indexed.
* Adding order subtraction test
Adding test for checking order for subtraction x- (y - z) x - (y + z).
* Updating to new PHP power operator
Updating from pow function to ** operator to clean up code.
* Updating to new removeWhere
Updating removeMatching to removeWhere because new version of Dart now use removeWhere.
* Fix for lua rounding assertequals
Adding check for number in equlity check for comparing number for floats.
* Adding test for copy of list
Adding test that checks the list is copied when a sublist is made first-last.
* Formatting and order fixes
Fixing formatting such as indentation and order fixes.
* Adding comment for clarity
Adding comment about how Lua code generation is not supporting zero indexing.
* Changed variable names in code
Changed variable names to follow style guide and changed for loop variable from n to i as is typical.
* Reducing unecessarily generated functions and renaming variables
Reducing number of generated functions using gensym_ by adding parameters to provided function. Renaming variables to make functions more readble.
* Fixing sublist order and sort variable
Fixing order used for valueToCode for sublist and renaming list variable in sort to match rest of code..
* Fixing order constant order
Removing operator () that was incorrect and addiung ~,
* Fixing order and indentation
Fixing order return fro create lists blocks and fixing indentationn for string array.
* Fixing order and renaming variables
Fixing order to be the correct strength and renaming variables to be more readable/
* Changing assert blocks for unit tests
Changing assert blocks to have a value input instead of a field so there is more flexibility in writing tests.
* Cleaning up and adding missing order tests
Adding tests for order for paramters for list blocks that weren't being tested to uncover bugs. Test were also cleaned up/reorganized/renamed to be more readable and shorter vertically (but lines wider horizontally).
* Compile error fix and order in Dart generation.
Fixing compile error in generated code and incorrect order in get sublist for Dart.
* Fixing typo in getIndex and invalid parameter name
Fixing type in getIndex where list code should have been appended but instead an undefined variable was added. The parameter in lists_sort was changed to my_list because list is a reserved word in python.
* Fixing order, parenthesis bug, and variable declaration in Lua
Fixing incorrect order in Lua. Fixing bug caused by missing parenthesis around ternary operator in code. Variable code was declared with JavaScript syntax, this was fixed to be valid in Lua.
* Adding tests and formatting tests
Adding missing test for order in text/lists. Changing spacing/order of tests and updating comments.
* Fixing error in code
Changing to correct function call in empy tests and changing test name that was duplicated to be more clear.
* Renamed test helper function
* Fixing order and renaming variable in JS generator
Fixing order for charAt and renaming variable in code list_sort from listCode to list to be consistent with rest of code.
* Fixing order for dart text
Fixing roder for dart charAt
* Cleaning up generated code for Dart getIndex
Cleaning up generated code for Dart getIndex so that helper functions aren't generated unecessarily and adding comments.
* Fixing Dart remove random error
Fixing error caused by remove random implementation in Dart. index should have been x but instead was length - x.
* Fixing unit test blocks
Fixing Lua unit test block that should have just returned the number and removing unecessary checks in other blocks because the constant was defined.
* Fixing Lua assert equals block
string.format was throwing an error if one of the values happened to be a boolean.
* Adding tests for create text with number
Adding test for create text with numbers as parameters
* Fixing lua unit test block
Lua unit test block should have added 1
* Removing indexing setting for Lua tests
Removing setting index setting for Lua generation because it is always one-indexed.
* Fixing order and create text
Fixing failing test caused by improper order and fixed create text to properly convert to string when there is one element.
* Running linter on generator code
Running linter on generator code and fixing spacing/indentation problems.
* Editing comments and removing uneeded parenthesis
Editing and adding comments and removing uneeded parenthesis around ternary operator condition.
* Fixing order and changing variable names
Fixing orders that were incorrect and changing variable names to be more descriptive and consistent across code.
* Adding comment about list support and fixes for PHP
Adding comment about how lists are not fully supported for PHP. Adding missing order to PHP and fixing order errors throughout. Fixing regex for variable matching in lists. Cleaning up variable names to be more readable and consistent with other parts of code.
* Reducing complexity for getremove/remove in JS
Reducing complexity in generated code for getremove/remove in JavaScript by replacing unecessary helper function.
* Fixing spacing before inline comments
Ensuring there are two spaces before inline comments.
* Changing JS list copy for clarity
Changing JavaScript list copy to use slice(0) instead of concat for clarity and to use the same pattern as the other sublist methods.
* Changing generated variable name tmp_x
Changing tmp_x to tmpX to follow closer to the correct style for JavaScript.
* Prefixing empy lines between comment text
Prior to this change, comments with an empty line between text did not have a comment prefix before it, resulting in comment blocks that seemed disjoined although they were for the same block. This change affects how the prefix line function works so that those lines will have the prefix (if applicable) while still taking into account the trailing newline character.
* Changing for loops variable names
Changing most for loops to use i as the variable name (or j if applicable) or changing name to be more readable.
* Simplifying provided subsequence function
Simplifying subsequence function to generate a simpler function depending on where combination instead of a larger complex function that works for all where combinations.
* Style fixes
Fixing indentation, comments, and other formatting-type changes based on pull request comments.
* Fixing indentation
Fixing indentation and removing an extra newline.
* Fixing PHP mode implementation
Fixing PHP mode implementation to properlyu return multiple modes if applicable.
* Fixing line too long
Wrapping lines in php/math.js with lines longer than 80 characters.
* Wrapping long lines
Wrapping lines that are too long.
* Changing boolean casing
Changing boolean casing to be lowercase.
---
core/field_angle.js | 6 +-
core/field_dropdown.js | 20 +-
core/field_variable.js | 4 +-
core/generator.js | 6 +-
core/input.js | 4 +-
core/procedures.js | 4 +-
core/rendered_connection.js | 16 +-
core/variables.js | 8 +-
demos/blockfactory/blocks.js | 10 +-
demos/blockfactory/factory.js | 4 +-
generators/dart.js | 97 +-
generators/dart/colour.js | 88 +-
generators/dart/lists.js | 514 +-
generators/dart/math.js | 228 +-
generators/dart/procedures.js | 12 +-
generators/dart/text.js | 211 +-
generators/javascript.js | 67 +-
generators/javascript/colour.js | 52 +-
generators/javascript/lists.js | 446 +-
generators/javascript/math.js | 64 +-
generators/javascript/text.js | 238 +-
generators/lua.js | 14 +-
generators/lua/lists.js | 251 +-
generators/lua/procedures.js | 12 +-
generators/lua/text.js | 73 +-
generators/php.js | 187 +-
generators/php/colour.js | 62 +-
generators/php/lists.js | 588 +-
generators/php/math.js | 115 +-
generators/php/procedures.js | 12 +-
generators/php/text.js | 177 +-
generators/php/variables.js | 2 +-
generators/python.js | 71 +-
generators/python/colour.js | 10 +-
generators/python/lists.js | 372 +-
generators/python/procedures.js | 12 +-
generators/python/text.js | 185 +-
tests/generators/colour.xml | 36 +-
tests/generators/functions.xml | 60 +-
tests/generators/index.html | 29 +-
tests/generators/lists.xml | 8185 +++++++++++++++++++----
tests/generators/logic.xml | 192 +-
tests/generators/loops1.xml | 28 +-
tests/generators/loops2.xml | 60 +-
tests/generators/loops3.xml | 48 +-
tests/generators/math.xml | 947 ++-
tests/generators/text.xml | 4057 ++++++++++-
tests/generators/unittest.js | 37 +-
tests/generators/unittest_dart.js | 27 +-
tests/generators/unittest_javascript.js | 35 +-
tests/generators/unittest_lua.js | 26 +-
tests/generators/unittest_php.js | 97 +-
tests/generators/unittest_python.js | 27 +-
tests/generators/variables.xml | 12 +-
tests/jsunit/connection_db_test.js | 4 +-
55 files changed, 14237 insertions(+), 3912 deletions(-)
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;
}