text.js 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. /**
  2. * @license Licensed under the Apache License, Version 2.0 (the "License"):
  3. * http://www.apache.org/licenses/LICENSE-2.0
  4. */
  5. /**
  6. * @fileoverview Arduino code generator for the text blocks.
  7. * Partially implements the Arduino Serial interface as described in:
  8. * http://arduino.cc/en/Reference/Serial
  9. *
  10. * TODO: Too many calls to String constructor, which consumes a lot of uC
  11. * resources. This will need revisiting for better type recognition.
  12. *
  13. * TODO: Trim generator is not correct.
  14. */
  15. 'use strict';
  16. goog.provide('Blockly.Python.text');
  17. goog.require('Blockly.Python');
  18. /**
  19. * Code generator for a literal String (X).
  20. * Arduino code: loop { "X" }
  21. * @param {!Blockly.Block} block Block to generate the code from.
  22. * @return {array} Completed code with order of operation.
  23. */
  24. Blockly.Python['text'] = function(block) {
  25. var code = Blockly.Python.quote_(block.getFieldValue('TEXT'));
  26. return [code, Blockly.Python.ORDER_ATOMIC];
  27. };
  28. /**
  29. * Code generator for a String concatenation (X...Y). This string can be made
  30. * up of any number of elements of any type.
  31. * This block uses a mutator.
  32. * String construction info: http://arduino.cc/en/Reference/StringConstructor
  33. * Arduino code: loop { "String(X)" + ... + "String(Y)" }
  34. * @param {!Blockly.Block} block Block to generate the code from.
  35. * @return {array} Completed code with order of operation.
  36. */
  37. Blockly.Python['text_join'] = function(block) {
  38. var code;
  39. if (block.itemCount_ == 0) {
  40. return ['""', Blockly.Python.ORDER_ATOMIC];
  41. } else if (block.itemCount_ == 1) {
  42. var argument0 = Blockly.Python.valueToCode(block, 'ADD0',
  43. Blockly.Python.ORDER_UNARY_POSTFIX) || '""';
  44. code = 'String(' + argument0 + ')';
  45. return [code, Blockly.Python.ORDER_UNARY_POSTFIX];
  46. } else {
  47. var argument;
  48. code = [];
  49. for (var n = 0; n < block.itemCount_; n++) {
  50. argument = Blockly.Python.valueToCode(
  51. block, 'ADD' + n, Blockly.Python.ORDER_NONE);
  52. if (argument == '') {
  53. code[n] = '""';
  54. } else {
  55. code[n] = 'String(' + argument + ')';
  56. }
  57. }
  58. code = code.join(' + ');
  59. return [code, Blockly.Python.ORDER_UNARY_POSTFIX];
  60. }
  61. };
  62. /**
  63. * Code generator for appending text (Y) to a variable in place (X).
  64. * String constructor info: http://arduino.cc/en/Reference/StringConstructor
  65. * Arduino code: loop { X += String(Y) }
  66. * @param {!Blockly.Block} block Block to generate the code from.
  67. * @return {string} Completed code.
  68. */
  69. Blockly.Python['text_append'] = function(block) {
  70. // Append to a variable in place.
  71. var varName = Blockly.Python.variableDB_.getName(
  72. block.getFieldValue('VAR'), Blockly.Variables.NAME_TYPE);
  73. var argument0 = Blockly.Python.valueToCode(block, 'TEXT',
  74. Blockly.Python.ORDER_UNARY_POSTFIX);
  75. if (argument0 == '') {
  76. argument0 = '""';
  77. } else {
  78. argument0 = 'String(' + argument0 + ')';
  79. }
  80. return varName + ' += ' + argument0 + ';\n';
  81. };
  82. /**
  83. * Code generator to get the length of a string (X).
  84. * String length info: http://arduino.cc/en/Reference/StringLength
  85. * Arduino code: loop { String(X).length() }
  86. * @param {!Blockly.Block} block Block to generate the code from.
  87. * @return {array} Completed code with order of operation.
  88. */
  89. Blockly.Python['text_length'] = function(block) {
  90. var argument0 = Blockly.Python.valueToCode(block, 'VALUE',
  91. Blockly.Python.ORDER_UNARY_POSTFIX) || '""';
  92. var code = 'String(' + argument0 + ').length()';
  93. return [code, Blockly.Python.ORDER_UNARY_POSTFIX];
  94. };
  95. /**
  96. * Code generator to test if a string (X) is null/empty.
  97. * String length info: http://arduino.cc/en/Reference/StringLength
  98. * Arduino code: boolean isStringEmpty(...) { ... }
  99. * loop { isStringEmpty(X) }
  100. * @param {!Blockly.Block} block Block to generate the code from.
  101. * @return {array} Completed code with order of operation.
  102. */
  103. Blockly.Python['text_isEmpty'] = function(block) {
  104. var func = [];
  105. func.push('boolean ' + Blockly.Python.DEF_FUNC_NAME + '(String msg) {');
  106. func.push(' if (msg.length() == 0) {');
  107. func.push(' return true;');
  108. func.push(' } else {');
  109. func.push(' return false;');
  110. func.push(' }');
  111. func.push('}');
  112. var funcName = Blockly.Python.addFunction('isStringEmpty', func.join('\n'));
  113. var argument0 = Blockly.Python.valueToCode(block, 'VALUE',
  114. Blockly.Python.ORDER_UNARY_POSTFIX);
  115. if (argument0 == '') {
  116. argument0 = '""';
  117. } else {
  118. argument0 = 'String(' + argument0 + ')';
  119. }
  120. var code = funcName + '(' + argument0 + ')';
  121. return [code, Blockly.Python.ORDER_UNARY_POSTFIX];
  122. };
  123. /**
  124. * Code generator to trim spaces from a string (X).
  125. * String trim info: http://arduino.cc/en/Tutorial/StringLengthTrim
  126. * Arduino code: loop { String(X).trim() }
  127. * @param {!Blockly.Block} block Block to generate the code from.
  128. * @return {array} Completed code with order of operation.
  129. */
  130. Blockly.Python['text_trim'] = function(block) {
  131. // Trim spaces.
  132. Blockly.Python.text_trim.OPERATORS = {
  133. LEFT: '.trim()',
  134. RIGHT: '.trim()',
  135. BOTH: '.trim()'
  136. };
  137. var mode = block.getFieldValue('MODE');
  138. var operator = Blockly.Python.text_trim.OPERATORS[mode];
  139. var argument0 = Blockly.Python.valueToCode(block, 'TEXT',
  140. Blockly.Python.ORDER_UNARY_POSTFIX);
  141. if (argument0 == '') {
  142. argument0 = '""';
  143. } else {
  144. argument0 = 'String(' + argument0 + ')';
  145. }
  146. return [argument0 + operator, Blockly.Python.ORDER_UNARY_POSTFIX];
  147. };
  148. /**
  149. * Code generator to print to the serial comm.
  150. * Serial info: http://arduino.cc/en/Reference/Serial
  151. * Arduino code: setup { Serial.begin(9600); }
  152. * loop { Serial.print(String(X)) }
  153. * @param {!Blockly.Block} block Block to generate the code from.
  154. * @return {string} Completed code.
  155. */
  156. Blockly.Python['text_print'] = function(block) {
  157. var serialId = Blockly.Python.Boards.selected.serial[0][1];
  158. var setupCode = serialId + '.begin(9600);';
  159. Blockly.Python.addSetup('serial_' + serialId, setupCode, false);
  160. var argument0 = Blockly.Python.valueToCode(block, 'TEXT',
  161. Blockly.Python.ORDER_NONE);
  162. if (argument0 == '') {
  163. argument0 = '""';
  164. } else {
  165. argument0 = 'String(' + argument0 + ')';
  166. }
  167. return serialId + '.print(' + argument0 + ');\n';
  168. };
  169. /**
  170. * Code generator to prompt the user with a string (X) and request input.
  171. * Serial info: http://arduino.cc/en/Reference/Serial
  172. * Arduino code: getUserInputPrompt(...) { ... }
  173. * loop { getUserInputPrompt("X")) }
  174. * @param {!Blockly.Block} block Block to generate the code from.
  175. * @return {array} Completed code with order of operation.
  176. */
  177. Blockly.Python['text_prompt_ext'] = function(block) {
  178. // Get the first Serial peripheral of arduino board
  179. var serialId = Blockly.Python.Boards.selected.serial[0][1];
  180. var returnType = block.getFieldValue('TYPE');
  181. // The function code changes based on reading a number or string
  182. var func = [];
  183. var toNumber = returnType == Blockly.Types.NUMBER.output;
  184. if (toNumber) {
  185. func.push('int ' + Blockly.Python.DEF_FUNC_NAME + '(String msg) {');
  186. } else {
  187. func.push('String ' + Blockly.Python.DEF_FUNC_NAME + '(String msg) {');
  188. }
  189. func.push(' ' + serialId + '.println(msg);');
  190. func.push(' boolean stringComplete = false;');
  191. if (toNumber) {
  192. func.push(' int content = 0;');// + serialId + '.parseInt();');
  193. } else {
  194. func.push(' String content = "";');
  195. }
  196. func.push(' while (stringComplete == false) {');
  197. func.push(' if (' + serialId + '.available()) {');
  198. if (toNumber) {
  199. func.push(' content = ' + serialId + '.parseInt();');
  200. func.push(' stringComplete = true;');
  201. } else {
  202. func.push(' char readChar = (char)' + serialId + '.read();');
  203. func.push(' if (readChar == \'\\n\' || readChar == \'\\r\') {');
  204. func.push(' stringComplete = true;');
  205. func.push(' } else {');
  206. func.push(' content += readChar;');
  207. func.push(' }');
  208. }
  209. func.push(' }');
  210. func.push(' }');
  211. func.push(' // Empty incoming serial buffer');
  212. func.push(' while(Serial.available()) { Serial.read(); };');
  213. func.push(' return content;');
  214. func.push('}');
  215. var funcName = Blockly.Python.addFunction(
  216. 'getUserInputPrompt' + returnType, func.join('\n'));
  217. // Only overwrite the serial set up if not present already
  218. var setupCode = serialId + '.begin(9600);';
  219. Blockly.Python.addSetup('serial_' + serialId, setupCode, false);
  220. var msg = Blockly.Python.valueToCode(block, 'TEXT',
  221. Blockly.Python.ORDER_NONE) || '""';
  222. var code = funcName + '(' + msg + ')';
  223. return [code, Blockly.Python.ORDER_UNARY_POSTFIX];
  224. };
  225. /* ***************************************************************** *
  226. * The rest of the blocks have been left unimplemented, as they have *
  227. * been removed from the toolbox and not used for Arduino code. *
  228. * ***************************************************************** */
  229. Blockly.Python['text_endString'] = function(block) {
  230. return ['', Blockly.Python.ORDER_UNARY_POSTFIX];
  231. };
  232. Blockly.Python['text_indexOf'] = function(block) {
  233. return ['', Blockly.Python.ORDER_UNARY_POSTFIX];
  234. };
  235. Blockly.Python['text_charAt'] = function(block) {
  236. return ['', Blockly.Python.ORDER_UNARY_POSTFIX];
  237. };
  238. Blockly.Python['text_getSubstring'] = function(block) {
  239. return ['', Blockly.Python.ORDER_UNARY_POSTFIX];
  240. };
  241. Blockly.Python['text_changeCase'] = function(block) {
  242. return ['', Blockly.Python.ORDER_UNARY_POSTFIX];
  243. };
  244. Blockly.Python['text_prompt'] = function(block) {
  245. return ['', Blockly.Python.ORDER_UNARY_POSTFIX];
  246. };