Automatic commit Sat Jan 11 03:00:02 PST 2014

This commit is contained in:
ellen.spertus
2014-01-11 03:00:02 -08:00
parent f29e70834f
commit 08f4022b38
43 changed files with 2067 additions and 1937 deletions

View File

@@ -112,6 +112,9 @@ Blockly.JavaScript.INFINITE_LOOP_TRAP = null;
Blockly.JavaScript.init = function() {
// Create a dictionary of definitions to be printed before the code.
Blockly.JavaScript.definitions_ = Object.create(null);
// Create a dictionary mapping desired function names in definitions_
// to actual function names (to avoid collisions with user functions).
Blockly.JavaScript.functionNames_ = Object.create(null);
if (Blockly.Variables) {
if (!Blockly.JavaScript.variableDB_) {

View File

@@ -36,18 +36,13 @@ Blockly.JavaScript['colour_picker'] = function(block) {
Blockly.JavaScript['colour_random'] = function(block) {
// Generate a random colour.
if (!Blockly.JavaScript.definitions_['colour_random']) {
var functionName = Blockly.JavaScript.variableDB_.getDistinctName(
'colour_random', Blockly.Generator.NAME_TYPE);
Blockly.JavaScript.colour_random.functionName = functionName;
var func = [];
func.push('function ' + functionName + '() {');
func.push(' var num = Math.floor(Math.random() * Math.pow(2, 24));');
func.push(' return \'#\' + (\'00000\' + num.toString(16)).substr(-6);');
func.push('}');
Blockly.JavaScript.definitions_['colour_random'] = func.join('\n');
}
var code = Blockly.JavaScript.colour_random.functionName + '()';
var functionName = Blockly.JavaScript.provideFunction_(
'colour_random',
[ 'function ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ + '() {',
' var num = Math.floor(Math.random() * Math.pow(2, 24));',
' return \'#\' + (\'00000\' + num.toString(16)).substr(-6);',
'}']);
var code = functionName + '()';
return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL];
};
@@ -59,25 +54,19 @@ Blockly.JavaScript['colour_rgb'] = function(block) {
Blockly.JavaScript.ORDER_COMMA) || 0;
var blue = Blockly.JavaScript.valueToCode(block, 'BLUE',
Blockly.JavaScript.ORDER_COMMA) || 0;
if (!Blockly.JavaScript.definitions_['colour_rgb']) {
var functionName = Blockly.JavaScript.variableDB_.getDistinctName(
'colour_rgb', Blockly.Generator.NAME_TYPE);
Blockly.JavaScript.colour_rgb.functionName = functionName;
var func = [];
func.push('function ' + functionName + '(r, g, b) {');
func.push(' r = Math.max(Math.min(Number(r), 100), 0) * 2.55;');
func.push(' g = Math.max(Math.min(Number(g), 100), 0) * 2.55;');
func.push(' b = Math.max(Math.min(Number(b), 100), 0) * 2.55;');
func.push(' r = (\'0\' + (Math.round(r) || 0).toString(16)).slice(-2);');
func.push(' g = (\'0\' + (Math.round(g) || 0).toString(16)).slice(-2);');
func.push(' b = (\'0\' + (Math.round(b) || 0).toString(16)).slice(-2);');
func.push(' return \'#\' + r + g + b;');
func.push('}');
Blockly.JavaScript.definitions_['colour_rgb'] = func.join('\n');
}
var code = Blockly.JavaScript.colour_rgb.functionName +
'(' + red + ', ' + green + ', ' + blue + ')';
var functionName = Blockly.JavaScript.provideFunction_(
'colour_rgb',
[ '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;',
'}']);
var code = functionName + '(' + red + ', ' + green + ', ' + blue + ')';
return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL];
};
@@ -89,31 +78,25 @@ Blockly.JavaScript['colour_blend'] = function(block) {
Blockly.JavaScript.ORDER_COMMA) || '\'#000000\'';
var ratio = Blockly.JavaScript.valueToCode(block, 'RATIO',
Blockly.JavaScript.ORDER_COMMA) || 0.5;
if (!Blockly.JavaScript.definitions_['colour_blend']) {
var functionName = Blockly.JavaScript.variableDB_.getDistinctName(
'colour_blend', Blockly.Generator.NAME_TYPE);
Blockly.JavaScript.colour_blend.functionName = functionName;
var func = [];
func.push('function ' + functionName + '(c1, c2, ratio) {');
func.push(' ratio = Math.max(Math.min(Number(ratio), 1), 0);');
func.push(' var r1 = parseInt(c1.substring(1, 3), 16);');
func.push(' var g1 = parseInt(c1.substring(3, 5), 16);');
func.push(' var b1 = parseInt(c1.substring(5, 7), 16);');
func.push(' var r2 = parseInt(c2.substring(1, 3), 16);');
func.push(' var g2 = parseInt(c2.substring(3, 5), 16);');
func.push(' var b2 = parseInt(c2.substring(5, 7), 16);');
func.push(' var r = Math.round(r1 * (1 - ratio) + r2 * ratio);');
func.push(' var g = Math.round(g1 * (1 - ratio) + g2 * ratio);');
func.push(' var b = Math.round(b1 * (1 - ratio) + b2 * ratio);');
func.push(' r = (\'0\' + (r || 0).toString(16)).slice(-2);');
func.push(' g = (\'0\' + (g || 0).toString(16)).slice(-2);');
func.push(' b = (\'0\' + (b || 0).toString(16)).slice(-2);');
func.push(' return \'#\' + r + g + b;');
func.push('}');
Blockly.JavaScript.definitions_['colour_blend'] = func.join('\n');
}
var code = Blockly.JavaScript.colour_blend.functionName +
'(' + c1 + ', ' + c2 + ', ' + ratio + ')';
var functionName = Blockly.JavaScript.provideFunction_(
'colour_blend',
[ '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;',
'}']);
var code = functionName + '(' + c1 + ', ' + c2 + ', ' + ratio + ')';
return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL];
};

View File

@@ -46,27 +46,21 @@ Blockly.JavaScript['lists_create_with'] = function(block) {
Blockly.JavaScript['lists_repeat'] = function(block) {
// Create a list with one element repeated.
if (!Blockly.JavaScript.definitions_['lists_repeat']) {
// Function copied from Closure's goog.array.repeat.
var functionName = Blockly.JavaScript.variableDB_.getDistinctName(
'lists_repeat', Blockly.Generator.NAME_TYPE);
Blockly.JavaScript.lists_repeat.repeat = functionName;
var func = [];
func.push('function ' + functionName + '(value, n) {');
func.push(' var array = [];');
func.push(' for (var i = 0; i < n; i++) {');
func.push(' array[i] = value;');
func.push(' }');
func.push(' return array;');
func.push('}');
Blockly.JavaScript.definitions_['lists_repeat'] = func.join('\n');
}
var functionName = Blockly.JavaScript.provideFunction_(
'lists_repeat',
[ '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',
Blockly.JavaScript.ORDER_COMMA) || 'null';
var argument1 = Blockly.JavaScript.valueToCode(block, 'NUM',
Blockly.JavaScript.ORDER_COMMA) || '0';
var code = Blockly.JavaScript.lists_repeat.repeat +
'(' + argument0 + ', ' + argument1 + ')';
var code = functionName + '(' + argument0 + ', ' + argument1 + ')';
return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL];
};
@@ -149,20 +143,14 @@ Blockly.JavaScript['lists_getIndex'] = function(block) {
var code = list + '.slice(-' + at + ')[0]';
return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL];
} else if (mode == 'GET_REMOVE' || mode == 'REMOVE') {
if (!Blockly.JavaScript.definitions_['lists_remove_from_end']) {
var functionName = Blockly.JavaScript.variableDB_.getDistinctName(
'lists_remove_from_end', Blockly.Generator.NAME_TYPE);
Blockly.JavaScript.lists_getIndex.lists_remove_from_end = functionName;
var func = [];
func.push('function ' + functionName + '(list, x) {');
func.push(' x = list.length - x;');
func.push(' return list.splice(x, 1)[0];');
func.push('}');
Blockly.JavaScript.definitions_['lists_remove_from_end'] =
func.join('\n');
}
code = Blockly.JavaScript.lists_getIndex.lists_remove_from_end +
'(' + list + ', ' + at + ')';
var functionName = Blockly.JavaScript.provideFunction_(
'lists_remove_from_end',
[ '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') {
return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL];
} else if (mode == 'REMOVE') {
@@ -170,24 +158,18 @@ Blockly.JavaScript['lists_getIndex'] = function(block) {
}
}
} else if (where == 'RANDOM') {
if (!Blockly.JavaScript.definitions_['lists_get_random_item']) {
var functionName = Blockly.JavaScript.variableDB_.getDistinctName(
'lists_get_random_item', Blockly.Generator.NAME_TYPE);
Blockly.JavaScript.lists_getIndex.random = functionName;
var func = [];
func.push('function ' + functionName + '(list, remove) {');
func.push(' var x = Math.floor(Math.random() * list.length);');
func.push(' if (remove) {');
func.push(' return list.splice(x, 1)[0];');
func.push(' } else {');
func.push(' return list[x];');
func.push(' }');
func.push('}');
Blockly.JavaScript.definitions_['lists_get_random_item'] =
func.join('\n');
}
code = Blockly.JavaScript.lists_getIndex.random +
'(' + list + ', ' + (mode != 'GET') + ')';
var functionName = Blockly.JavaScript.provideFunction_(
'lists_get_random_item',
[ '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') {
@@ -288,35 +270,29 @@ Blockly.JavaScript['lists_getSublist'] = function(block) {
if (where1 == 'FIRST' && where2 == 'LAST') {
var code = list + '.concat()';
} else {
if (!Blockly.JavaScript.definitions_['lists_get_sublist']) {
var functionName = Blockly.JavaScript.variableDB_.getDistinctName(
'lists_get_sublist', Blockly.Generator.NAME_TYPE);
Blockly.JavaScript.lists_getSublist.func = functionName;
var func = [];
func.push('function ' + functionName +
'(list, where1, at1, where2, at2) {');
func.push(' function getAt(where, at) {');
func.push(' if (where == \'FROM_START\') {');
func.push(' at--;');
func.push(' } else if (where == \'FROM_END\') {');
func.push(' at = list.length - at;');
func.push(' } else if (where == \'FIRST\') {');
func.push(' at = 0;');
func.push(' } else if (where == \'LAST\') {');
func.push(' at = list.length - 1;');
func.push(' } else {');
func.push(' throw \'Unhandled option (lists_getSublist).\';');
func.push(' }');
func.push(' return at;');
func.push(' }');
func.push(' at1 = getAt(where1, at1);');
func.push(' at2 = getAt(where2, at2) + 1;');
func.push(' return list.slice(at1, at2);');
func.push('}');
Blockly.JavaScript.definitions_['lists_get_sublist'] =
func.join('\n');
}
var code = Blockly.JavaScript.lists_getSublist.func + '(' + list + ', \'' +
var functionName = Blockly.JavaScript.provideFunction_(
'lists_get_sublist',
[ '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);',
'}']);
var code = functionName + '(' + list + ', \'' +
where1 + '\', ' + at1 + ', \'' + where2 + '\', ' + at2 + ')';
}
return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL];

View File

@@ -164,33 +164,28 @@ Blockly.JavaScript['math_number_property'] = function(block) {
var code;
if (dropdown_property == 'PRIME') {
// Prime is a special case as it is not a one-liner test.
if (!Blockly.JavaScript.definitions_['isPrime']) {
var functionName = Blockly.JavaScript.variableDB_.getDistinctName(
'isPrime', Blockly.Generator.NAME_TYPE);
Blockly.JavaScript.logic_prime= functionName;
var func = [];
func.push('function ' + functionName + '(n) {');
func.push(' // http://en.wikipedia.org/wiki/Primality_test#Naive_methods');
func.push(' if (n == 2 || n == 3) {');
func.push(' return true;');
func.push(' }');
func.push(' // False if n is NaN, negative, is 1, or not whole.');
func.push(' // And false if n is divisible by 2 or 3.');
func.push(' if (isNaN(n) || n <= 1 || n % 1 != 0 || n % 2 == 0 ||' +
' n % 3 == 0) {');
func.push(' return false;');
func.push(' }');
func.push(' // Check all the numbers of form 6k +/- 1, up to sqrt(n).');
func.push(' for (var x = 6; x <= Math.sqrt(n) + 1; x += 6) {');
func.push(' if (n % (x - 1) == 0 || n % (x + 1) == 0) {');
func.push(' return false;');
func.push(' }');
func.push(' }');
func.push(' return true;');
func.push('}');
Blockly.JavaScript.definitions_['isPrime'] = func.join('\n');
}
code = Blockly.JavaScript.logic_prime + '(' + number_to_check + ')';
var functionName = Blockly.JavaScript.provideFunction_(
'math_isPrime',
[ '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;',
'}']);
code = functionName + '(' + number_to_check + ')';
return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL];
}
switch (dropdown_property) {
@@ -255,131 +250,107 @@ Blockly.JavaScript['math_on_list'] = function(block) {
break;
case 'AVERAGE':
// math_median([null,null,1,3]) == 2.0.
if (!Blockly.JavaScript.definitions_['math_mean']) {
var functionName = Blockly.JavaScript.variableDB_.getDistinctName(
'math_mean', Blockly.Generator.NAME_TYPE);
Blockly.JavaScript.math_on_list.math_mean = functionName;
var func = [];
func.push('function ' + functionName + '(myList) {');
func.push(' return myList.reduce(function(x, y) {return x + y;}) / ' +
'myList.length;');
func.push('}');
Blockly.JavaScript.definitions_['math_mean'] = func.join('\n');
}
var functionName = Blockly.JavaScript.provideFunction_(
'math_mean',
[ 'function ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ +
'(myList) {',
' return myList.reduce(function(x, y) {return x + y;}) / ' +
'myList.length;',
'}']);
list = Blockly.JavaScript.valueToCode(block, 'LIST',
Blockly.JavaScript.ORDER_NONE) || '[]';
code = Blockly.JavaScript.math_on_list.math_mean + '(' + list + ')';
code = functionName + '(' + list + ')';
break;
case 'MEDIAN':
// math_median([null,null,1,3]) == 2.0.
if (!Blockly.JavaScript.definitions_['math_median']) {
var functionName = Blockly.JavaScript.variableDB_.getDistinctName(
'math_median', Blockly.Generator.NAME_TYPE);
Blockly.JavaScript.math_on_list.math_median = functionName;
var func = [];
func.push('function ' + functionName + '(myList) {');
func.push(' var localList = myList.filter(function (x) ' +
'{return typeof x == \'number\';});');
func.push(' if (!localList.length) return null;');
func.push(' localList.sort(function(a, b) {return b - a;});');
func.push(' if (localList.length % 2 == 0) {');
func.push(' return (localList[localList.length / 2 - 1] + ' +
'localList[localList.length / 2]) / 2;');
func.push(' } else {');
func.push(' return localList[(localList.length - 1) / 2];');
func.push(' }');
func.push('}');
Blockly.JavaScript.definitions_['math_median'] = func.join('\n');
}
var functionName = Blockly.JavaScript.provideFunction_(
'math_median',
[ 'function ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ +
'(myList) {',
' var localList = myList.filter(function (x) ' +
'{return typeof x == \'number\';});',
' if (!localList.length) return null;',
' localList.sort(function(a, b) {return b - a;});',
' if (localList.length % 2 == 0) {',
' return (localList[localList.length / 2 - 1] + ' +
'localList[localList.length / 2]) / 2;',
' } else {',
' return localList[(localList.length - 1) / 2];',
' }',
'}']);
list = Blockly.JavaScript.valueToCode(block, 'LIST',
Blockly.JavaScript.ORDER_NONE) || '[]';
code = Blockly.JavaScript.math_on_list.math_median + '(' + list + ')';
code = functionName + '(' + list + ')';
break;
case 'MODE':
if (!Blockly.JavaScript.definitions_['math_modes']) {
var functionName = Blockly.JavaScript.variableDB_.getDistinctName(
'math_modes', Blockly.Generator.NAME_TYPE);
Blockly.JavaScript.math_on_list.math_modes = functionName;
// As a list of numbers can contain more than one mode,
// the returned result is provided as an array.
// Mode of [3, 'x', 'x', 1, 1, 2, '3'] -> ['x', 1].
var func = [];
func.push('function ' + functionName + '(values) {');
func.push(' var modes = [];');
func.push(' var counts = [];');
func.push(' var maxCount = 0;');
func.push(' for (var i = 0; i < values.length; i++) {');
func.push(' var value = values[i];');
func.push(' var found = false;');
func.push(' var thisCount;');
func.push(' for (var j = 0; j < counts.length; j++) {');
func.push(' if (counts[j][0] === value) {');
func.push(' thisCount = ++counts[j][1];');
func.push(' found = true;');
func.push(' break;');
func.push(' }');
func.push(' }');
func.push(' if (!found) {');
func.push(' counts.push([value, 1]);');
func.push(' thisCount = 1;');
func.push(' }');
func.push(' maxCount = Math.max(thisCount, maxCount);');
func.push(' }');
func.push(' for (var j = 0; j < counts.length; j++) {');
func.push(' if (counts[j][1] == maxCount) {');
func.push(' modes.push(counts[j][0]);');
func.push(' }');
func.push(' }');
func.push(' return modes;');
func.push('}');
Blockly.JavaScript.definitions_['math_modes'] = func.join('\n');
}
// As a list of numbers can contain more than one mode,
// the returned result is provided as an array.
// Mode of [3, 'x', 'x', 1, 1, 2, '3'] -> ['x', 1].
var functionName = Blockly.JavaScript.provideFunction_(
'math_modes',
[ 'function ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ +
'(values) {',
' var modes = [];',
' var counts = [];',
' var maxCount = 0;',
' for (var i = 0; i < values.length; i++) {',
' var value = values[i];',
' var found = false;',
' var thisCount;',
' for (var j = 0; j < counts.length; j++) {',
' if (counts[j][0] === value) {',
' thisCount = ++counts[j][1];',
' found = true;',
' break;',
' }',
' }',
' if (!found) {',
' counts.push([value, 1]);',
' thisCount = 1;',
' }',
' maxCount = Math.max(thisCount, maxCount);',
' }',
' for (var j = 0; j < counts.length; j++) {',
' if (counts[j][1] == maxCount) {',
' modes.push(counts[j][0]);',
' }',
' }',
' return modes;',
'}']);
list = Blockly.JavaScript.valueToCode(block, 'LIST',
Blockly.JavaScript.ORDER_NONE) || '[]';
code = Blockly.JavaScript.math_on_list.math_modes + '(' + list + ')';
code = functionName + '(' + list + ')';
break;
case 'STD_DEV':
if (!Blockly.JavaScript.definitions_['math_standard_deviation']) {
var functionName = Blockly.JavaScript.variableDB_.getDistinctName(
'math_standard_deviation', Blockly.Generator.NAME_TYPE);
Blockly.JavaScript.math_on_list.math_standard_deviation = functionName;
var func = [];
func.push('function ' + functionName + '(numbers) {');
func.push(' var n = numbers.length;');
func.push(' if (!n) return null;');
func.push(' var mean = numbers.reduce(function(x, y) ' +
'{return x + y;}) / n;');
func.push(' var variance = 0;');
func.push(' for (var j = 0; j < n; j++) {');
func.push(' variance += Math.pow(numbers[j] - mean, 2);');
func.push(' }');
func.push(' variance = variance / n;');
func.push(' return Math.sqrt(variance);');
func.push('}');
Blockly.JavaScript.definitions_['math_standard_deviation'] =
func.join('\n');
}
var functionName = Blockly.JavaScript.provideFunction_(
'math_standard_deviation',
[ 'function ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ +
'(numbers) {',
' var n = numbers.length;',
' if (!n) return null;',
' var mean = numbers.reduce(function(x, y) {return x + y;}) / n;',
' var variance = 0;',
' for (var j = 0; j < n; j++) {',
' variance += Math.pow(numbers[j] - mean, 2);',
' }',
' variance = variance / n;',
' return Math.sqrt(variance);',
'}']);
list = Blockly.JavaScript.valueToCode(block, 'LIST',
Blockly.JavaScript.ORDER_NONE) || '[]';
code = Blockly.JavaScript.math_on_list.math_standard_deviation +
'(' + list + ')';
code = functionName + '(' + list + ')';
break;
case 'RANDOM':
if (!Blockly.JavaScript.definitions_['math_random_item']) {
var functionName = Blockly.JavaScript.variableDB_.getDistinctName(
'math_random_item', Blockly.Generator.NAME_TYPE);
Blockly.JavaScript.math_on_list.math_random_item = functionName;
var func = [];
func.push('function ' + functionName + '(list) {');
func.push(' var x = Math.floor(Math.random() * list.length);');
func.push(' return list[x];');
func.push('}');
Blockly.JavaScript.definitions_['math_random_item'] = func.join('\n');
}
var functionName = Blockly.JavaScript.provideFunction_(
'math_random_list',
[ 'function ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ +
'(list) {',
' var x = Math.floor(Math.random() * list.length);',
' return list[x];',
'}']);
list = Blockly.JavaScript.valueToCode(block, 'LIST',
Blockly.JavaScript.ORDER_NONE) || '[]';
code = Blockly.JavaScript.math_on_list.math_random_item +
'(' + list + ')';
code = functionName + '(' + list + ')';
break;
default:
throw 'Unknown operator: ' + func;
@@ -416,24 +387,19 @@ Blockly.JavaScript['math_random_int'] = function(block) {
Blockly.JavaScript.ORDER_COMMA) || '0';
var argument1 = Blockly.JavaScript.valueToCode(block, 'TO',
Blockly.JavaScript.ORDER_COMMA) || '0';
if (!Blockly.JavaScript.definitions_['math_random_int']) {
var functionName = Blockly.JavaScript.variableDB_.getDistinctName(
'math_random_int', Blockly.Generator.NAME_TYPE);
Blockly.JavaScript.math_random_int.random_function = functionName;
var func = [];
func.push('function ' + functionName + '(a, b) {');
func.push(' if (a > b) {');
func.push(' // Swap a and b to ensure a is smaller.');
func.push(' var c = a;');
func.push(' a = b;');
func.push(' b = c;');
func.push(' }');
func.push(' return Math.floor(Math.random() * (b - a + 1) + a);');
func.push('}');
Blockly.JavaScript.definitions_['math_random_int'] = func.join('\n');
}
var code = Blockly.JavaScript.math_random_int.random_function +
'(' + argument0 + ', ' + argument1 + ')';
var functionName = Blockly.JavaScript.provideFunction_(
'math_random_int',
[ '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);',
'}']);
var code = functionName + '(' + argument0 + ', ' + argument1 + ')';
return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL];
};

View File

@@ -127,19 +127,14 @@ Blockly.JavaScript['text_charAt'] = function(block) {
var code = text + '.slice(-' + at + ').charAt(0)';
return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL];
case 'RANDOM':
if (!Blockly.JavaScript.definitions_['text_random_letter']) {
var functionName = Blockly.JavaScript.variableDB_.getDistinctName(
'text_random_letter', Blockly.Generator.NAME_TYPE);
Blockly.JavaScript.text_charAt.text_random_letter = functionName;
var func = [];
func.push('function ' + functionName + '(text) {');
func.push(' var x = Math.floor(Math.random() * text.length);');
func.push(' return text[x];');
func.push('}');
Blockly.JavaScript.definitions_['text_random_letter'] = func.join('\n');
}
code = Blockly.JavaScript.text_charAt.text_random_letter +
'(' + text + ')';
var functionName = Blockly.JavaScript.provideFunction_(
'text_random_letter',
[ 'function ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ +
'(text) {',
' var x = Math.floor(Math.random() * text.length);',
' return text[x];',
'}']);
code = functionName + '(' + text + ')';
return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL];
}
throw 'Unhandled option (text_charAt).';
@@ -158,35 +153,29 @@ Blockly.JavaScript['text_getSubstring'] = function(block) {
if (where1 == 'FIRST' && where2 == 'LAST') {
var code = text;
} else {
if (!Blockly.JavaScript.definitions_['text_get_substring']) {
var functionName = Blockly.JavaScript.variableDB_.getDistinctName(
'text_get_substring', Blockly.Generator.NAME_TYPE);
Blockly.JavaScript.text_getSubstring.func = functionName;
var func = [];
func.push('function ' + functionName +
'(text, where1, at1, where2, at2) {');
func.push(' function getAt(where, at) {');
func.push(' if (where == \'FROM_START\') {');
func.push(' at--;');
func.push(' } else if (where == \'FROM_END\') {');
func.push(' at = text.length - at;');
func.push(' } else if (where == \'FIRST\') {');
func.push(' at = 0;');
func.push(' } else if (where == \'LAST\') {');
func.push(' at = text.length - 1;');
func.push(' } else {');
func.push(' throw \'Unhandled option (text_getSubstring).\';');
func.push(' }');
func.push(' return at;');
func.push(' }');
func.push(' at1 = getAt(where1, at1);');
func.push(' at2 = getAt(where2, at2) + 1;');
func.push(' return text.slice(at1, at2);');
func.push('}');
Blockly.JavaScript.definitions_['text_get_substring'] =
func.join('\n');
}
var code = Blockly.JavaScript.text_getSubstring.func + '(' + text + ', \'' +
var functionName = Blockly.JavaScript.provideFunction_(
'text_get_substring',
[ '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);',
'}']);
var code = functionName + '(' + text + ', \'' +
where1 + '\', ' + at1 + ', \'' + where2 + '\', ' + at2 + ')';
}
return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL];
@@ -207,23 +196,17 @@ Blockly.JavaScript['text_changeCase'] = function(block) {
Blockly.JavaScript.ORDER_MEMBER) || '\'\'';
code = argument0 + operator;
} else {
if (!Blockly.JavaScript.definitions_['text_toTitleCase']) {
// Title case is not a native JavaScript function. Define one.
var functionName = Blockly.JavaScript.variableDB_.getDistinctName(
'text_toTitleCase', Blockly.Generator.NAME_TYPE);
Blockly.JavaScript.text_changeCase.toTitleCase = functionName;
var func = [];
func.push('function ' + functionName + '(str) {');
func.push(' return str.replace(/\\S+/g,');
func.push(' function(txt) {return txt[0].toUpperCase() + ' +
'txt.substring(1).toLowerCase();});');
func.push('}');
Blockly.JavaScript.definitions_['text_toTitleCase'] = func.join('\n');
}
// Title case is not a native JavaScript function. Define one.
var functionName = Blockly.JavaScript.provideFunction_(
'text_toTitleCase',
[ '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 = Blockly.JavaScript.text_changeCase.toTitleCase +
'(' + argument0 + ')';
code = functionName + '(' + argument0 + ')';
}
return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL];
};

View File

@@ -82,16 +82,6 @@ Blockly.Python.ORDER_NONE = 99; // (...)
*/
Blockly.Python.INFINITE_LOOP_TRAP = null;
/**
* This is used as a placeholder in functions defined using
* Blockly.Python.provideFunction_. It must not be legal code that could
* legitimately appear in a function definition (or comment), and it must
* not confuse the regular expression parser.
*/
Blockly.Python.FUNCTION_NAME_PLACEHOLDER_ = '{{{}}}';
Blockly.Python.FUNCTION_NAME_PLACEHOLDER_REGEXP_ =
new RegExp(Blockly.Python.FUNCTION_NAME_PLACEHOLDER_, 'g');
/**
* Initialise the database of variable names.
*/
@@ -207,31 +197,3 @@ Blockly.Python.scrub_ = function(block, code) {
var nextCode = this.blockToCode(nextBlock);
return commentCode + code + nextCode;
};
/**
* Define a function to be included in the generated code.
* The first time this is called with a given desiredName, the code is
* saved and an actual name is generated. Subsequent calls with the
* same desiredName have no effect but have the same return value.
*
* It is up to the caller to make sure the same desiredName is not
* used for different code values.
*
* The code gets output when Blockly.Python.finish() is called.
*
* @param {string} desiredName The desired name of the function (e.g., isPrime).
* @param {code} A list of Python statements.
* @return {string} The actual name of the new function. This may differ
* from desiredName if the former has already been taken by the user.
* @private
*/
Blockly.Python.provideFunction_ = function(desiredName, code) {
if (!Blockly.Python.definitions_[desiredName]) {
var functionName = Blockly.Python.variableDB_.getDistinctName(
desiredName, Blockly.Generator.NAME_TYPE);
Blockly.Python.functionNames_[desiredName] = functionName;
Blockly.Python.definitions_[desiredName] = code.join('\n').replace(
Blockly.Python.FUNCTION_NAME_PLACEHOLDER_REGEXP_, functionName);
}
return Blockly.Python.functionNames_[desiredName];
};

View File

@@ -42,7 +42,7 @@ Blockly.Python['colour_random'] = function(block) {
};
Blockly.Python['colour_rgb'] = function(block) {
// Compose a colour from RGB components.
// 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):',

View File

@@ -170,9 +170,9 @@ Blockly.Python['math_number_property'] = function(block) {
if (dropdown_property == 'PRIME') {
Blockly.Python.definitions_['import_math'] = 'import math';
var functionName = Blockly.Python.provideFunction_(
'isPrime',
'math_isPrime',
['def ' + Blockly.Python.FUNCTION_NAME_PLACEHOLDER_ + '(n):',
' # http://en.wikipedia.org/wiki/Primality_test#Naive_methods',
' # https://en.wikipedia.org/wiki/Primality_test#Naive_methods',
' # If n is not a number but a string, try parsing it.',
' if type(n) not in (int, float, long):',
' try:',