code_generator.js 38 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315
  1. // iVProg - www.usp.br/line/ivprog
  2. // LInE - Free Education, Private Data
  3. // eslint-disable @typescript-eslint/no-use-before-define
  4. // globals $
  5. import { Types } from "./types";
  6. import * as Models from "./ivprog_elements";
  7. import { LocalizedStrings } from "./../services/localizedStringsService";
  8. import * as Utils from "./utils";
  9. // Code to main function
  10. export function generate () {
  11. $(".ivprog_visual_panel").find(".error_icon").remove();
  12. let code = LocalizedStrings.getUI("program") + " { ";
  13. code += globalsCode();
  14. code += "\n";
  15. let has_error = false;
  16. for (let i = 0; i < window.program_obj.functions.length; i++) {
  17. const n_code = functionsCode(window.program_obj.functions[i]);
  18. if (n_code == null) {
  19. has_error = true;
  20. }
  21. code += n_code;
  22. code += "\n";
  23. }
  24. code += "\n}";
  25. if (has_error) {
  26. return null;
  27. } else {
  28. return code;
  29. }
  30. }
  31. function functionsCode (function_obj) {
  32. let ret = "\n " + LocalizedStrings.getUI("function") + " "; // not \t - using fixed space to indentation
  33. const has_error = false;
  34. switch (function_obj.return_type) {
  35. case Types.INTEGER:
  36. ret += LocalizedStrings.getUI("type_integer");
  37. break;
  38. case Types.REAL:
  39. ret += LocalizedStrings.getUI("type_real");
  40. break;
  41. case Types.TEXT:
  42. ret += LocalizedStrings.getUI("type_text");
  43. break;
  44. case Types.BOOLEAN:
  45. ret += LocalizedStrings.getUI("type_boolean");
  46. break;
  47. case Types.CHAR:
  48. ret += LocalizedStrings.getUI("type_char");
  49. break;
  50. case Types.VOID:
  51. ret += LocalizedStrings.getUI("type_void");
  52. break;
  53. }
  54. ret += " ";
  55. if (function_obj.return_dimensions == 1) {
  56. ret += "[] ";
  57. } else if (function_obj.return_dimensions == 2) {
  58. ret += "[][] ";
  59. }
  60. if (function_obj.is_main) {
  61. ret += LocalizedStrings.getUI("start");
  62. } else {
  63. ret += function_obj.name;
  64. }
  65. ret += " ("; // open parameter to function
  66. for (let j = 0; j < function_obj.parameters_list.length; j++) {
  67. ret += parametersCode(function_obj.parameters_list[j]);
  68. if (j + 1 < function_obj.parameters_list.length) {
  69. ret += ", ";
  70. }
  71. }
  72. ret += ") {"; // close parameters to function
  73. for (let j = 0; j < function_obj.variables_list.length; j++) {
  74. ret += variablesCode(function_obj.variables_list[j]);
  75. }
  76. for (let j = 0; j < function_obj.commands.length; j++) {
  77. //D try {
  78. ret += commandsCode(function_obj.commands[j]);
  79. /* //D } catch (err) {
  80. has_error = true; console.error(err.message); var todos = $('body').find('.command_container');
  81. for (var i = 0; i < todos.length; i++) { if ($(todos[i]).data('command') == function_obj.commands[j]) {
  82. $( todos[i] ).prepend(' <i class="ui icon red exclamation triangle error_icon"></i> '); break;
  83. } } }*/
  84. }
  85. ret += "\n }"; // close function - "\n\t" using fixed space to indentation
  86. if (has_error) {
  87. return null;
  88. } else {
  89. return ret;
  90. }
  91. }
  92. function commandsCode (command_obj, indentation = 2) {
  93. let code = "";
  94. switch (command_obj.type) {
  95. case Models.COMMAND_TYPES.break:
  96. code = breaksCode(command_obj, indentation);
  97. break;
  98. case Models.COMMAND_TYPES.comment:
  99. code = commentsCode(command_obj, indentation);
  100. break;
  101. case Models.COMMAND_TYPES.reader:
  102. code = readersCode(command_obj, indentation);
  103. break;
  104. case Models.COMMAND_TYPES.writer:
  105. code = writersCode(command_obj, indentation);
  106. break;
  107. case Models.COMMAND_TYPES.functioncall:
  108. code = functioncallsCode(command_obj, indentation);
  109. break;
  110. case Models.COMMAND_TYPES.attribution:
  111. code = attributionsCode(command_obj, indentation);
  112. break;
  113. case Models.COMMAND_TYPES.whiletrue:
  114. code = whiletruesCode(command_obj, indentation);
  115. break;
  116. case Models.COMMAND_TYPES.dowhiletrue:
  117. code = doWhilesCode(command_obj, indentation);
  118. break;
  119. case Models.COMMAND_TYPES.iftrue:
  120. code = iftruesCode(command_obj, indentation);
  121. break;
  122. case Models.COMMAND_TYPES.repeatNtimes:
  123. code = repeatNtimesCode(command_obj, indentation);
  124. break;
  125. case Models.COMMAND_TYPES.switch:
  126. code = switchsCode(command_obj, indentation);
  127. break;
  128. case Models.COMMAND_TYPES.return:
  129. code = returnsCode(command_obj, indentation);
  130. break;
  131. }
  132. // IMPORTANT: do NOT add inline comment here!
  133. // Each specific function (whiletruesCode, etc) does this
  134. // To add here implies to DOUBLE the comment!
  135. // Add comment if, and only if, is a simple command (without blocks)
  136. const simpleCommands = [
  137. Models.COMMAND_TYPES.break,
  138. Models.COMMAND_TYPES.reader,
  139. Models.COMMAND_TYPES.writer,
  140. Models.COMMAND_TYPES.functioncall,
  141. Models.COMMAND_TYPES.attribution,
  142. Models.COMMAND_TYPES.return,
  143. ];
  144. if (simpleCommands.includes(command_obj.type)) {
  145. code = addInlineComment(code, command_obj);
  146. }
  147. return code;
  148. } // function commandsCode(command_obj, indentation = 2)
  149. function returnsCode (command_obj, indentation) {
  150. let ret = "\n";
  151. for (let i = 0; i < indentation; i++) {
  152. ret += " "; // do not use "\t" - better using 2 fixed spaces as indentation
  153. }
  154. ret += LocalizedStrings.getUI("text_return");
  155. if (command_obj.variable_value_menu) {
  156. try {
  157. ret += " " + elementExpressionCode(command_obj.variable_value_menu);
  158. //ret += ' ' + variableValueMenuCode(command_obj.variable_value_menu, true);
  159. } catch (err) {
  160. //Empty block
  161. }
  162. }
  163. return ret;
  164. }
  165. function breaksCode (_command_obj, indentation) {
  166. let ret = "\n";
  167. for (let i = 0; i < indentation; i++) {
  168. ret += " "; // "\t" - using fixed space to indentation
  169. }
  170. ret += LocalizedStrings.getUI("text_break");
  171. return ret;
  172. }
  173. // Write Switch code
  174. function switchsCode (command_obj, indentation) {
  175. let ret = "\n";
  176. for (let i = 0; i < indentation; i++) {
  177. ret += " "; // do not use "\t" - better using 2 fixed spaces as indentation
  178. }
  179. ret += LocalizedStrings.getUI("text_code_switch") + "(";
  180. ret += variableValueMenuCode(command_obj.variable);
  181. ret += ") { ";
  182. if (command_obj.cases) {
  183. for (let i = 0; i < command_obj.cases.length; i++) {
  184. ret += switchcasesCode(command_obj.cases[i], indentation + 1);
  185. }
  186. }
  187. ret += "\n";
  188. for (let i = 0; i < indentation; i++) {
  189. ret += " "; // do not use "\t" - better using 2 fixed spaces as indentation
  190. }
  191. ret += "} ";
  192. return ret;
  193. }
  194. function switchcasesCode (switchcase, indentation) {
  195. let ret = "\n";
  196. for (let i = 0; i < indentation; i++) {
  197. ret += " "; // do not use "\t" - better using 2 fixed spaces as indentation
  198. }
  199. ret += LocalizedStrings.getUI("text_code_case") + " ";
  200. ret += variableValueMenuCode(switchcase.variable_value_menu);
  201. ret += " :";
  202. if (switchcase.commands_block) {
  203. for (let i = 0; i < switchcase.commands_block.length; i++) {
  204. ret += commandsCode(switchcase.commands_block[i], indentation + 1);
  205. }
  206. }
  207. return ret;
  208. }
  209. export function repeatNtimesHeader (command_obj) {
  210. let ret = "";
  211. if (command_obj.var_attribution) {
  212. ret += '<span class="repeatN_text_par_1">';
  213. ret += variableValueMenuCode(command_obj.var_attribution);
  214. ret += '</span>';
  215. //leo ret += ` ${LocalizedStrings.getUI("text_code_for_from")} `;
  216. ret += ' ' + LocalizedStrings.getUI("text_code_for_from") + ' ';
  217. ret += '<span class="repeatN_text_par_2">';
  218. ret += variableValueMenuCode(command_obj.expression1);
  219. ret += '</span>';
  220. }
  221. //D var ret1 = LocalizedStrings.getUI("text_code_for_from") + ' ';
  222. //D var ret2 = ` ${LocalizedStrings.getUI("text_code_for_from")} `;
  223. //D console.log("********** code_generator.js: repeatNtimesHeader(.): 1 ret=" + ret1 + "\n" + ret2 + "\n"); //leo remover xxxxxxxxxxx
  224. if (command_obj.expression2) {
  225. //leo ret += ` ${LocalizedStrings.getUI("text_code_for_to")} `;
  226. ret += ' ' + LocalizedStrings.getUI("text_code_for_to") + ' ';
  227. ret += '<span class="repeatN_text_par_3">';
  228. ret += variableValueMenuCode(command_obj.expression2);
  229. ret += '</span>';
  230. }
  231. if (command_obj.expression3) {
  232. //leo ret += ` ${LocalizedStrings.getUI("text_code_for_pass")} `;
  233. ret += ' ' + LocalizedStrings.getUI("text_code_for_pass") + ' ';
  234. ret += '<span class="repeatN_text_par_4">';
  235. switch (command_obj.expression3.itens[1]) {
  236. case Models.ARITHMETIC_TYPES.plus:
  237. ret += " +";
  238. break;
  239. case Models.ARITHMETIC_TYPES.minus:
  240. ret += " -";
  241. break;
  242. }
  243. ret += variableValueMenuCode(command_obj.expression3.itens[2]);
  244. ret += '</span>';
  245. }
  246. return ret;
  247. }
  248. function repeatNtimesCode (command_obj, indentation) {
  249. let ret = "\n";
  250. for (let i = 0; i < indentation; i++) {
  251. ret += " "; // do not use "\t" - better using 2 fixed spaces as indentation
  252. }
  253. ret += LocalizedStrings.getUI("text_for") + " ";
  254. if (command_obj.var_attribution) {
  255. ret += variableValueMenuCode(command_obj.var_attribution);
  256. ret += ` ${LocalizedStrings.getUI("text_code_for_from")} `;
  257. ret += variableValueMenuCode(command_obj.expression1);
  258. }
  259. if (command_obj.expression2) {
  260. ret += ` ${LocalizedStrings.getUI("text_code_for_to")} `;
  261. ret += variableValueMenuCode(command_obj.expression2);
  262. }
  263. if (command_obj.expression3) {
  264. ret += ` ${LocalizedStrings.getUI("text_code_for_pass")} `;
  265. // To fix the bug UNDEFINED
  266. // The problem is inside the struture of expression3
  267. console.log("DEBUG expression3:", command_obj.expression3);
  268. // Try to access in more than one form
  269. let operator = null;
  270. let operand = null;
  271. // Verify if is ExpressionElement with items
  272. if (command_obj.expression3.itens) {
  273. operator = command_obj.expression3.itens[1];
  274. operand = command_obj.expression3.itens[2];
  275. }
  276. // Verify if has direct structure (what is "direct structure"?)
  277. else if (command_obj.expression3.operator) {
  278. operator = command_obj.expression3.operator;
  279. operand = command_obj.expression3.operand || command_obj.expression3.value;
  280. }
  281. // Try (directly) array
  282. else if (Array.isArray(command_obj.expression3)) {
  283. operator = command_obj.expression3[0];
  284. operand = command_obj.expression3[1];
  285. }
  286. // Render operator (build operator to be HTML presented)
  287. if (operator) {
  288. switch (operator) {
  289. case Models.ARITHMETIC_TYPES.plus:
  290. ret += "+";
  291. break;
  292. case Models.ARITHMETIC_TYPES.minus:
  293. ret += "-";
  294. break;
  295. default:
  296. ret += "+"; // fallback
  297. }
  298. } else {
  299. ret += "+"; // fallback
  300. }
  301. // Render operand (build operand to be HTML presented)
  302. if (operand) {
  303. ret += variableValueMenuCode(operand);
  304. } else {
  305. ret += "1"; // fallback
  306. }
  307. }
  308. ret += " {";
  309. // Add inline comment ONLY ONCE HERE
  310. if (command_obj.inlineComment) {
  311. ret += " // " + command_obj.inlineComment;
  312. }
  313. if (command_obj.commands_block) {
  314. for (let i = 0; i < command_obj.commands_block.length; i++) {
  315. ret += commandsCode(command_obj.commands_block[i], indentation + 1);
  316. }
  317. }
  318. ret += "\n";
  319. for (let i = 0; i < indentation; i++) {
  320. ret += " "; // do not use "\t" - better using 2 fixed spaces as indentation
  321. }
  322. ret += "}";
  323. // here, do not add "another" inline comment!
  324. return ret;
  325. } // function repeatNtimesCode(command_obj, indentation)
  326. // Write IfElse code
  327. // Whenever "click" to see "textual code"
  328. function iftruesCode (command_obj, indentation) {
  329. let ret = "\n";
  330. //D console.log("code_generator.js!iftruesCode(.): "); //leo
  331. for (let i = 0; i < indentation; i++) {
  332. ret += " "; // do not use "\t" - better using 2 fixed spaces as indentation
  333. }
  334. ret += LocalizedStrings.getUI("text_if");
  335. if (command_obj.expression) {
  336. ret += "(";
  337. ret += elementExpressionCode(command_obj.expression);
  338. ret += ")";
  339. } else {
  340. //NOT necessary: Utils.renderErrorMessage(command_obj.expression.dom_object, LocalizedStrings.getUI("inform_valid_expression"));
  341. }
  342. ret += " {";
  343. // Inline comment ONLY here
  344. if (command_obj.inlineComment) {
  345. ret += " // " + command_obj.inlineComment;
  346. }
  347. if (command_obj.commands_block) {
  348. for (let i = 0; i < command_obj.commands_block.length; i++) {
  349. ret += commandsCode(command_obj.commands_block[i], indentation + 1);
  350. }
  351. }
  352. ret += "\n";
  353. for (let i = 0; i < indentation; i++) {
  354. ret += " "; // do not use "\t" - better using 2 fixed spaces as indentation
  355. }
  356. ret += "} " + LocalizedStrings.getUI("text_else") + " {";
  357. if (command_obj.commands_else) {
  358. for (let i = 0; i < command_obj.commands_else.length; i++) {
  359. ret += commandsCode(command_obj.commands_else[i], indentation + 1);
  360. }
  361. }
  362. ret += "\n";
  363. for (let i = 0; i < indentation; i++) {
  364. ret += " "; // do not use "\t" - better using 2 fixed spaces as indentation
  365. }
  366. ret += "}";
  367. return ret;
  368. } // function iftruesCode(command_obj, indentation)
  369. function doWhilesCode (command_obj, indentation) {
  370. let ret = "\n";
  371. for (let i = 0; i < indentation; i++) {
  372. ret += " "; // do not use "\t" - better using 2 fixed spaces as indentation
  373. }
  374. ret += LocalizedStrings.getUI("text_code_do") + " {";
  375. if (command_obj.inlineComment) {
  376. ret += " // " + command_obj.inlineComment;
  377. }
  378. if (command_obj.commands_block) {
  379. for (let i = 0; i < command_obj.commands_block.length; i++) {
  380. ret += commandsCode(command_obj.commands_block[i], indentation + 1);
  381. }
  382. }
  383. ret += "\n";
  384. for (let i = 0; i < indentation; i++) {
  385. ret += " "; // do not use "\t" - better using 2 fixed spaces as indentation
  386. }
  387. ret += "} " + LocalizedStrings.getUI("text_code_do_until");
  388. //x if (!command_obj.expression) { Utils.renderErrorMessage(command_obj.expression.dom_object, LocalizedStrings.getUI("inform_valid_expression")); }
  389. if (command_obj.expression) {
  390. ret += "(";
  391. ret += elementExpressionCode(command_obj.expression);
  392. ret += ")";
  393. }
  394. return ret;
  395. } // function doWhilesCode(command_obj, indentation)
  396. function whiletruesCode (command_obj, indentation) {
  397. let ret = "\n";
  398. for (let i = 0; i < indentation; i++) {
  399. ret += " "; // do not use "\t" - better using 2 fixed spaces as indentation
  400. }
  401. ret += LocalizedStrings.getUI("text_code_while");
  402. //x if (!command_obj.expression) Utils.renderErrorMessage(command_obj.expression.dom_object, LocalizedStrings.getUI("inform_valid_expression"));
  403. if (command_obj.expression) {
  404. ret += "(";
  405. ret += elementExpressionCode(command_obj.expression);
  406. ret += ")";
  407. }
  408. ret += " {";
  409. if (command_obj.inlineComment) {
  410. ret += " // " + command_obj.inlineComment;
  411. }
  412. if (command_obj.commands_block) {
  413. for (let i = 0; i < command_obj.commands_block.length; i++) {
  414. ret += commandsCode(command_obj.commands_block[i], indentation + 1);
  415. }
  416. }
  417. ret += "\n";
  418. for (let i = 0; i < indentation; i++) {
  419. ret += " "; // do not use "\t" - better using 2 fixed spaces as indentation
  420. }
  421. ret += "}";
  422. return ret;
  423. } // function whiletruesCode(command_obj, indentation)
  424. function logicExpressionCode (expression) {
  425. let ret = "(";
  426. if (expression.first_operand.type == Models.EXPRESSION_TYPES.exp_logic) {
  427. ret += logicExpressionCode(expression.first_operand);
  428. } else if (
  429. expression.first_operand.type == Models.EXPRESSION_TYPES.exp_arithmetic
  430. ) {
  431. ret += arithmeticExpressionCode(expression.first_operand);
  432. } else {
  433. ret += variableValueMenuCode(expression.first_operand);
  434. }
  435. if (expression.operator) {
  436. switch (expression.operator) {
  437. case Models.LOGIC_COMPARISON.equals_to:
  438. ret += " == ";
  439. break;
  440. case Models.LOGIC_COMPARISON.not_equals_to:
  441. ret += " != ";
  442. break;
  443. case Models.LOGIC_COMPARISON.and:
  444. ret += " && ";
  445. break;
  446. case Models.LOGIC_COMPARISON.or:
  447. ret += " || ";
  448. break;
  449. }
  450. if (expression.second_operand.type == Models.EXPRESSION_TYPES.exp_logic) {
  451. ret += logicExpressionCode(expression.second_operand);
  452. } else if (
  453. expression.second_operand.type == Models.EXPRESSION_TYPES.exp_arithmetic
  454. ) {
  455. ret += arithmeticExpressionCode(expression.second_operand);
  456. } else {
  457. ret += variableValueMenuCode(expression.second_operand);
  458. }
  459. }
  460. ret += ")";
  461. return ret;
  462. } // function logicExpressionCode(expression)
  463. function arithmeticExpressionCode (expression) {
  464. let ret = "(";
  465. if (expression.first_operand.type == Models.EXPRESSION_TYPES.exp_logic) {
  466. ret += logicExpressionCode(expression.first_operand);
  467. } else if (
  468. expression.first_operand.type == Models.EXPRESSION_TYPES.exp_arithmetic
  469. ) {
  470. ret += arithmeticExpressionCode(expression.first_operand);
  471. } else {
  472. ret += variableValueMenuCode(expression.first_operand);
  473. }
  474. switch (expression.operator) {
  475. case Models.ARITHMETIC_COMPARISON.greater_than:
  476. ret += " > ";
  477. break;
  478. case Models.ARITHMETIC_COMPARISON.less_than:
  479. ret += " < ";
  480. break;
  481. case Models.ARITHMETIC_COMPARISON.equals_to:
  482. ret += " == ";
  483. break;
  484. case Models.ARITHMETIC_COMPARISON.not_equals_to:
  485. ret += " != ";
  486. break;
  487. case Models.ARITHMETIC_COMPARISON.greater_than_or_equals_to:
  488. ret += " >= ";
  489. break;
  490. case Models.ARITHMETIC_COMPARISON.less_than_or_equals_to:
  491. ret += " <= ";
  492. break;
  493. }
  494. if (expression.second_operand.type == Models.EXPRESSION_TYPES.exp_logic) {
  495. ret += logicExpressionCode(expression.second_operand);
  496. } else if (
  497. expression.second_operand.type == Models.EXPRESSION_TYPES.exp_arithmetic
  498. ) {
  499. ret += arithmeticExpressionCode(expression.second_operand);
  500. } else {
  501. ret += variableValueMenuCode(expression.second_operand);
  502. }
  503. ret += ")";
  504. return ret;
  505. } // function arithmeticExpressionCode(expression)
  506. function attributionsCode (command_obj, indentation) {
  507. let ret = "\n";
  508. for (let i = 0; i < indentation; i++) {
  509. ret += " "; // do not use "\t" - better using 2 fixed spaces as indentation
  510. }
  511. ret += variableValueMenuCode(command_obj.variable) + " <- ";
  512. // for (var i = 0; i < command_obj.expression.length; i++) { ret += elementExpressionCode(command_obj.expression[i]); }
  513. ret += elementExpressionCode(command_obj.expression);
  514. return ret;
  515. }
  516. export function elementExpressionCode (expression_obj) {
  517. let ret = "";
  518. for (let i = 0; i < expression_obj.length; i++) {
  519. if (expression_obj[i].type) {
  520. ret += variableValueMenuCode(expression_obj[i]);
  521. } else if (expression_obj[i].type_op) {
  522. switch (expression_obj[i].item) {
  523. case Models.ARITHMETIC_TYPES.plus:
  524. ret += " + ";
  525. break;
  526. case Models.ARITHMETIC_TYPES.minus:
  527. ret += " - ";
  528. break;
  529. case Models.ARITHMETIC_TYPES.multiplication:
  530. ret += " * ";
  531. break;
  532. case Models.ARITHMETIC_TYPES.division:
  533. ret += " / ";
  534. break;
  535. case Models.ARITHMETIC_TYPES.module:
  536. ret += " % ";
  537. break;
  538. case Models.LOGIC_COMPARISON.equals_to:
  539. ret += " == ";
  540. break;
  541. case Models.LOGIC_COMPARISON.not_equals_to:
  542. ret += " != ";
  543. break;
  544. case Models.LOGIC_COMPARISON.and:
  545. ret += " " + LocalizedStrings.getUI("logic_operator_and") + " ";
  546. break;
  547. case Models.LOGIC_COMPARISON.or:
  548. ret += " " + LocalizedStrings.getUI("logic_operator_or") + " ";
  549. break;
  550. case Models.LOGIC_COMPARISON.not:
  551. ret += " " + LocalizedStrings.getUI("logic_operator_not") + " ";
  552. break;
  553. case Models.ARITHMETIC_COMPARISON.greater_than:
  554. ret += " > ";
  555. break;
  556. case Models.ARITHMETIC_COMPARISON.less_than:
  557. ret += " < ";
  558. break;
  559. case Models.ARITHMETIC_COMPARISON.greater_than_or_equals_to:
  560. ret += " >= ";
  561. break;
  562. case Models.ARITHMETIC_COMPARISON.less_than_or_equals_to:
  563. ret += " <= ";
  564. break;
  565. case Models.EXPRESSION_TYPES.write_sep:
  566. ret += ', " ", ';
  567. break;
  568. }
  569. } else {
  570. ret += " " + expression_obj[i] + " ";
  571. }
  572. }
  573. return ret;
  574. } // export function elementExpressionCode(expression_obj)
  575. function functioncallsCode (command_obj, indentation) {
  576. let ret = "\n";
  577. for (let i = 0; i < indentation; i++) {
  578. ret += " "; // do not use "\t" - better using 2 fixed spaces as indentation
  579. }
  580. ret += variableValueMenuCode(command_obj.function_called);
  581. return ret;
  582. }
  583. // Presents "write(.)" command in iVProg graphical interface
  584. function readersCode (command_obj, indentation) {
  585. let ret = "\n";
  586. for (let i = 0; i < indentation; i++) {
  587. ret += " "; // do not use "\t" - better using 2 fixed spaces as indentation
  588. }
  589. ret += LocalizedStrings.getUI("text_command_read") + "("; // open
  590. ret += variableValueMenuCode(command_obj.variable_value_menu);
  591. ret += ")"; // close
  592. return ret;
  593. }
  594. export function variableValueMenuCode (variable_obj, is_return = false) {
  595. let ret = "";
  596. try {
  597. if (variable_obj.function_called) {
  598. if (variable_obj.function_called.name) {
  599. ret += variable_obj.function_called.name + "("; // open
  600. } else {
  601. ret += LocalizedStrings.translateInternalFunction(variable_obj.function_called.identifier, variable_obj.function_called.category) + "(";
  602. }
  603. if (variable_obj.parameters_list) {
  604. for (let i = 0; i < variable_obj.parameters_list.length; i++) {
  605. ret += variableValueMenuCode(variable_obj.parameters_list[i]);
  606. if (i + 1 < variable_obj.parameters_list.length) {
  607. ret += ", ";
  608. }
  609. }
  610. }
  611. ret += ")"; // close
  612. //D console.log("********** code_generator.js: variableValueMenuCode(.): ret=" + ret); //leo remover xxxxxxxxxxx
  613. } else if (variable_obj.content.type) {
  614. ret += variable_obj.content.name;
  615. if (variable_obj.content.dimensions == 1 && variable_obj.dimensions != 1) {
  616. ret += "[" + variableValueMenuCode(variable_obj.column) + "]"; // array
  617. }
  618. if (variable_obj.content.dimensions == 2 && variable_obj.dimensions != 2 && variable_obj.reference_dimensions == 1) {
  619. ret += "[" + variableValueMenuCode(variable_obj.row) + "]"; // array
  620. } else if (variable_obj.content.dimensions == 2 && variable_obj.dimensions != 2) {
  621. ret += "[" + variableValueMenuCode(variable_obj.row) + "]"; // array
  622. ret += "[" + variableValueMenuCode(variable_obj.column) + "]"; // array
  623. }
  624. } else {
  625. const content = String(variable_obj.content);
  626. if (isNaN(content)) {
  627. // console.debug("Content length: ", content.length);
  628. // console.debug("Char code at 0", content.charCodeAt(0));
  629. const isBackslash = content.charCodeAt(0) === 92;
  630. if (content.length === 1 || (content.length === 2 && isBackslash)) {
  631. ret += `'${content}'`;
  632. } else {
  633. ret += '"' + variable_obj.content + '"';
  634. }
  635. } else if (content.length == 0) {
  636. ret += '""';
  637. } else if (content.trim().length == 0) {
  638. ret += '"' + content + '"';
  639. } else {
  640. ret += variable_obj.content;
  641. }
  642. }
  643. } catch (err) {
  644. var str = variable_obj==null || variable_obj==undefined ? "empty" : variable_obj.content; //D
  645. console.log("js/visualUI/code_generator.js!variableValueMenuCode(.): Error, variable_obj.content=" + str); //D
  646. if (!is_return) {
  647. Utils.renderErrorMessage(variable_obj.dom_object, LocalizedStrings.getUI("inform_valid_content"));
  648. throw err;
  649. }
  650. }
  651. return ret;
  652. } // export function variableValueMenuCode(variable_obj, is_return = false)
  653. // Write to file command "write(.)"
  654. function writersCode (command_obj, indentation) {
  655. let ret = "\n";
  656. for (let i = 0; i < indentation; i++) {
  657. ret += " "; // do not use "\t" - better using 2 fixed spaces as indentation
  658. }
  659. ret += LocalizedStrings.getUI("text_command_write") + "(";
  660. /*for (var i = 0; i < command_obj.content.length; i++) {
  661. ret += variableValueMenuCode(command_obj.content[i]);
  662. if ((i + 1) < command_obj.content.length) { ret += ' + ';}
  663. }*/
  664. ret += elementExpressionCode(command_obj.content);
  665. if (command_obj.newline) {
  666. ret += ', "\\n"';
  667. }
  668. ret += ") ";
  669. return ret;
  670. }
  671. function commentsCode (command_obj, indentation) {
  672. let ret = "\n";
  673. for (let i = 0; i < indentation; i++) {
  674. ret += " "; // do not use "\t" - better using 2 fixed spaces as indentation
  675. }
  676. ret += "// ";
  677. //comment stars (Edilson)
  678. let commentText = "";
  679. if (command_obj.comment_text) {
  680. if (typeof command_obj.comment_text === "object" && command_obj.comment_text.content) {
  681. commentText = command_obj.comment_text.content;
  682. } else if (typeof command_obj.comment_text === "string") {
  683. commentText = command_obj.comment_text;
  684. }
  685. }
  686. if (!commentText) {
  687. commentText = command_obj.value || command_obj.comment || command_obj._text || "";
  688. }
  689. ret += commentText;
  690. //comments ends (Edilson)
  691. return ret;
  692. }
  693. function parametersCode (parameter_obj) {
  694. let ret = "";
  695. switch (parameter_obj.type) {
  696. case Types.INTEGER:
  697. ret += " " + LocalizedStrings.getUI("type_integer") + " ";
  698. break;
  699. case Types.REAL:
  700. ret += " " + LocalizedStrings.getUI("type_real") + " ";
  701. break;
  702. case Types.TEXT:
  703. ret += " " + LocalizedStrings.getUI("type_text") + " ";
  704. break;
  705. case Types.BOOLEAN:
  706. ret += " " + LocalizedStrings.getUI("type_boolean") + " ";
  707. break;
  708. case Types.CHAR:
  709. ret += " " + LocalizedStrings.getUI("type_char") + " ";
  710. break;
  711. }
  712. if (parameter_obj.reference)
  713. ret += "&";
  714. ret += parameter_obj.name + "";
  715. if (parameter_obj.dimensions == 1) {
  716. ret += " []";
  717. } else if (parameter_obj.dimensions == 2) {
  718. ret += " [][]";
  719. }
  720. return ret;
  721. }
  722. // Write variable declaration code
  723. function variablesCode (variable_obj) {
  724. if (variable_obj.type === "comment" || variable_obj.constructor.name === "Comment") {
  725. return commentsCode(variable_obj, 2);
  726. }
  727. let ret = "";
  728. const temp = variable_obj;
  729. ret += "\n "; // "\n\t\n" - using fixed space to indentation (adjust to the function indentation)
  730. if (temp.is_constant) {
  731. ret += "const ";
  732. }
  733. switch (temp.type) {
  734. case Types.INTEGER:
  735. ret += LocalizedStrings.getUI("type_integer") + " ";
  736. break;
  737. case Types.REAL:
  738. ret += LocalizedStrings.getUI("type_real") + " ";
  739. break;
  740. case Types.TEXT:
  741. ret += LocalizedStrings.getUI("type_text") + " ";
  742. break;
  743. case Types.BOOLEAN:
  744. ret += LocalizedStrings.getUI("type_boolean") + " ";
  745. break;
  746. case Types.CHAR:
  747. ret += LocalizedStrings.getUI("type_char") + " ";
  748. break;
  749. }
  750. ret += temp.name + " ";
  751. if (temp.dimensions == 1) {
  752. ret += "[" + temp.columns + "] ";
  753. switch (temp.type) {
  754. case Types.INTEGER:
  755. ret += "<- {";
  756. for (let j = 0; j < temp.value.length; j++) {
  757. ret += temp.value[j];
  758. if (j + 1 < temp.value.length) {
  759. ret += ", ";
  760. }
  761. }
  762. ret += "}";
  763. break;
  764. case Types.REAL:
  765. ret += "<- {";
  766. for (let j = 0; j < temp.value.length; j++) {
  767. ret += parseFloat(temp.value[j]).toFixed(2);
  768. if (j + 1 < temp.value.length) {
  769. ret += ", ";
  770. }
  771. }
  772. ret += "}";
  773. break;
  774. case Types.TEXT:
  775. ret += "<- {";
  776. for (let j = 0; j < temp.value.length; j++) {
  777. ret += '"' + temp.value[j] + '"';
  778. if (j + 1 < temp.value.length) {
  779. ret += ", ";
  780. }
  781. }
  782. ret += "}";
  783. break;
  784. case Types.BOOLEAN:
  785. ret += "<- {";
  786. for (let j = 0; j < temp.value.length; j++) {
  787. if (temp.value[j]) {
  788. ret += LocalizedStrings.getUI("logic_value_true");
  789. } else {
  790. ret += LocalizedStrings.getUI("logic_value_false");
  791. }
  792. if (j + 1 < temp.value.length) {
  793. ret += ", ";
  794. }
  795. }
  796. ret += "}";
  797. break;
  798. case Types.CHAR:
  799. ret += "<- {";
  800. for (let j = 0; j < temp.value.length; j++) {
  801. ret += "'" + temp.value[j] + "'";
  802. if (j + 1 < temp.value.length) {
  803. ret += ", ";
  804. }
  805. }
  806. ret += "}";
  807. break;
  808. }
  809. } else if (temp.dimensions == 2) {
  810. ret += "[" + temp.rows + "][" + temp.columns + "] ";
  811. switch (temp.type) {
  812. case Types.INTEGER:
  813. ret += "<- {";
  814. for (let j = 0; j < temp.rows; j++) {
  815. ret += "{";
  816. for (let k = 0; k < temp.columns; k++) {
  817. ret += temp.value[j][k];
  818. if (k + 1 < temp.columns) {
  819. ret += ", ";
  820. }
  821. }
  822. ret += "}";
  823. if (j + 1 < temp.rows) {
  824. ret += ", ";
  825. }
  826. }
  827. ret += "}";
  828. break;
  829. case Types.REAL:
  830. ret += "<- {";
  831. for (let j = 0; j < temp.rows; j++) {
  832. ret += "{";
  833. for (let k = 0; k < temp.columns; k++) {
  834. ret += parseFloat(temp.value[j][k]).toFixed(2);
  835. if (k + 1 < temp.columns) {
  836. ret += ", ";
  837. }
  838. }
  839. ret += "}";
  840. if (j + 1 < temp.rows) {
  841. ret += ", ";
  842. }
  843. }
  844. ret += "}";
  845. break;
  846. case Types.TEXT:
  847. ret += "<- {";
  848. for (let j = 0; j < temp.rows; j++) {
  849. ret += "{";
  850. for (let k = 0; k < temp.columns; k++) {
  851. ret += '"' + temp.value[j][k] + '"';
  852. if (k + 1 < temp.columns) {
  853. ret += ", ";
  854. }
  855. }
  856. ret += "}";
  857. if (j + 1 < temp.rows) {
  858. ret += ", ";
  859. }
  860. }
  861. ret += "}";
  862. break;
  863. case Types.BOOLEAN:
  864. ret += "<- {";
  865. for (let j = 0; j < temp.rows; j++) {
  866. ret += "{";
  867. for (let k = 0; k < temp.columns; k++) {
  868. if (temp.value[j][k]) {
  869. ret += LocalizedStrings.getUI("logic_value_true");
  870. } else {
  871. ret += LocalizedStrings.getUI("logic_value_false");
  872. }
  873. if (k + 1 < temp.columns) {
  874. ret += ", ";
  875. }
  876. }
  877. ret += "}";
  878. if (j + 1 < temp.rows) {
  879. ret += ", ";
  880. }
  881. }
  882. ret += "}";
  883. break;
  884. case Types.CHAR:
  885. ret += "<- {";
  886. for (let j = 0; j < temp.rows; j++) {
  887. ret += "{";
  888. for (let k = 0; k < temp.columns; k++) {
  889. ret += "'" + temp.value[j][k] + "'";
  890. if (k + 1 < temp.columns) {
  891. ret += ", ";
  892. }
  893. }
  894. ret += "}";
  895. if (j + 1 < temp.rows) {
  896. ret += ", ";
  897. }
  898. }
  899. ret += "}";
  900. break;
  901. }
  902. } else {
  903. switch (temp.type) {
  904. case Types.INTEGER:
  905. ret += "<- " + temp.value;
  906. break;
  907. case Types.REAL:
  908. ret += "<- " + parseFloat(temp.value).toFixed(2);
  909. break;
  910. case Types.TEXT:
  911. ret += '<- "' + temp.value + '"';
  912. break;
  913. case Types.BOOLEAN:
  914. ret += "<- ";
  915. if (temp.value) {
  916. ret += LocalizedStrings.getUI("logic_value_true");
  917. } else {
  918. ret += LocalizedStrings.getUI("logic_value_false");
  919. }
  920. break;
  921. case Types.CHAR:
  922. ret += "<- '" + temp.value + "'";
  923. break;
  924. }
  925. }
  926. ret = addInlineComment(ret, temp); //comments (Edilson)
  927. return ret;
  928. } // function variablesCode(variable_obj)
  929. function globalsCode () {
  930. let ret = "";
  931. if (window.program_obj.globals) {
  932. for (let i = 0; i < window.program_obj.globals.length; i++) {
  933. const temp = window.program_obj.globals[i];
  934. ret += " "; // do not use "\t" - better using 2 fixed spaces as indentation
  935. if (temp.is_constant) {
  936. ret += "const "; //TODO Internacionalizar - insert it in ./ivprog/i18n/ui.csv
  937. }
  938. switch (temp.type) {
  939. case Types.INTEGER:
  940. ret += LocalizedStrings.getUI("type_integer");
  941. break;
  942. case Types.REAL:
  943. ret += LocalizedStrings.getUI("type_real");
  944. break;
  945. case Types.TEXT:
  946. ret += LocalizedStrings.getUI("type_text");
  947. break;
  948. case Types.BOOLEAN:
  949. ret += LocalizedStrings.getUI("type_boolean");
  950. break;
  951. case Types.CHAR:
  952. ret += LocalizedStrings.getUI("type_char");
  953. break;
  954. }
  955. ret += " " + temp.name + " ";
  956. if (temp.dimensions == 1) {
  957. ret += "[" + temp.columns + "] ";
  958. switch (temp.type) {
  959. case Types.INTEGER:
  960. ret += "<- {";
  961. for (let j = 0; j < temp.value.length; j++) {
  962. ret += temp.value[j];
  963. if (j + 1 < temp.value.length) {
  964. ret += ", ";
  965. }
  966. }
  967. ret += "}";
  968. break;
  969. case Types.REAL:
  970. ret += "<- {";
  971. for (let j = 0; j < temp.value.length; j++) {
  972. ret += parseFloat(temp.value[j]).toFixed(2);
  973. if (j + 1 < temp.value.length) {
  974. ret += ", ";
  975. }
  976. }
  977. ret += "}";
  978. break;
  979. case Types.TEXT:
  980. ret += "<- {";
  981. for (let j = 0; j < temp.value.length; j++) {
  982. ret += '"' + temp.value[j] + '"';
  983. if (j + 1 < temp.value.length) {
  984. ret += ", ";
  985. }
  986. }
  987. ret += "}";
  988. break;
  989. case Types.BOOLEAN:
  990. ret += "<- {";
  991. for (let j = 0; j < temp.value.length; j++) {
  992. if (temp.value[j]) {
  993. ret += LocalizedStrings.getUI("logic_value_true");
  994. } else {
  995. ret += LocalizedStrings.getUI("logic_value_false");
  996. }
  997. if (j + 1 < temp.value.length) {
  998. ret += ", ";
  999. }
  1000. }
  1001. ret += "}";
  1002. break;
  1003. case Types.CHAR:
  1004. ret += "<- {";
  1005. for (let j = 0; j < temp.value.length; j++) {
  1006. ret += "'" + temp.value[j] + "'";
  1007. if (j + 1 < temp.value.length) {
  1008. ret += ", ";
  1009. }
  1010. }
  1011. ret += "}";
  1012. break;
  1013. }
  1014. } else if (temp.dimensions == 2) {
  1015. ret += "[" + temp.rows + "][" + temp.columns + "] ";
  1016. switch (temp.type) {
  1017. case Types.INTEGER:
  1018. ret += "<- {";
  1019. for (let j = 0; j < temp.rows; j++) {
  1020. ret += "{";
  1021. for (let k = 0; k < temp.columns; k++) {
  1022. ret += temp.value[j][k];
  1023. if (k + 1 < temp.columns) {
  1024. ret += ", ";
  1025. }
  1026. }
  1027. ret += "}";
  1028. if (j + 1 < temp.rows) {
  1029. ret += ", ";
  1030. }
  1031. }
  1032. ret += "}";
  1033. break;
  1034. case Types.REAL:
  1035. ret += "<- {";
  1036. for (let j = 0; j < temp.rows; j++) {
  1037. ret += "{";
  1038. for (let k = 0; k < temp.columns; k++) {
  1039. ret += parseFloat(temp.value[j][k]).toFixed(2);
  1040. if (k + 1 < temp.columns) {
  1041. ret += ", ";
  1042. }
  1043. }
  1044. ret += "}";
  1045. if (j + 1 < temp.rows) {
  1046. ret += ", ";
  1047. }
  1048. }
  1049. ret += "}";
  1050. break;
  1051. case Types.TEXT:
  1052. ret += "<- {";
  1053. for (let j = 0; j < temp.rows; j++) {
  1054. ret += "{";
  1055. for (let k = 0; k < temp.columns; k++) {
  1056. ret += '"' + temp.value[j][k] + '"';
  1057. if (k + 1 < temp.columns) {
  1058. ret += ", ";
  1059. }
  1060. }
  1061. ret += "}";
  1062. if (j + 1 < temp.rows) {
  1063. ret += ", ";
  1064. }
  1065. }
  1066. ret += "}";
  1067. break;
  1068. case Types.BOOLEAN:
  1069. ret += "<- {";
  1070. for (let j = 0; j < temp.rows; j++) {
  1071. ret += "{";
  1072. for (let k = 0; k < temp.columns; k++) {
  1073. if (temp.value[j][k]) {
  1074. ret += LocalizedStrings.getUI("logic_value_true");
  1075. } else {
  1076. ret += LocalizedStrings.getUI("logic_value_false");
  1077. }
  1078. if (k + 1 < temp.columns) {
  1079. ret += ", ";
  1080. }
  1081. }
  1082. ret += "}";
  1083. if (j + 1 < temp.rows) {
  1084. ret += ", ";
  1085. }
  1086. }
  1087. ret += "}";
  1088. break;
  1089. case Types.CHAR:
  1090. ret += "<- {";
  1091. for (let j = 0; j < temp.rows; j++) {
  1092. ret += "{";
  1093. for (let k = 0; k < temp.columns; k++) {
  1094. ret += "'" + temp.value[j][k] + "'";
  1095. if (k + 1 < temp.columns) {
  1096. ret += ", ";
  1097. }
  1098. }
  1099. ret += "}";
  1100. if (j + 1 < temp.rows) {
  1101. ret += ", ";
  1102. }
  1103. }
  1104. ret += "}";
  1105. break;
  1106. }
  1107. } else {
  1108. switch (temp.type) {
  1109. case Types.INTEGER:
  1110. ret += "<- " + temp.value;
  1111. break;
  1112. case Types.REAL:
  1113. ret += "<- " + parseFloat(temp.value).toFixed(2);
  1114. break;
  1115. case Types.TEXT:
  1116. ret += '<- "' + temp.value + '"';
  1117. break;
  1118. case Types.BOOLEAN:
  1119. ret += "<- ";
  1120. if (temp.value) {
  1121. ret += LocalizedStrings.getUI("logic_value_true");
  1122. } else {
  1123. ret += LocalizedStrings.getUI("logic_value_false");
  1124. }
  1125. break;
  1126. case Types.CHAR:
  1127. ret += "<- '" + temp.value + "'";
  1128. break;
  1129. }
  1130. }
  1131. }
  1132. }
  1133. return ret;
  1134. } // function globalsCode()
  1135. // Treat comments (Edilson)
  1136. function addInlineComment (code, command_obj) {
  1137. if (command_obj.inlineComment) {
  1138. return code.trimEnd() + " // " + command_obj.inlineComment;
  1139. }
  1140. return code;
  1141. }