You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

84 lines
2.2 KiB

4 years ago
  1. #!/usr/bin/env node
  2. // This script converts for and do-while loops into equivalent while loops.
  3. // Note that for-in statements are left unmodified, as they do not have a
  4. // simple analogy to while loops. Also note that labeled continue statements
  5. // are not correctly handled at this point, and will trigger an assertion
  6. // failure if encountered.
  7. var assert = require("assert");
  8. var recast = require("recast");
  9. var types = recast.types;
  10. var n = types.namedTypes;
  11. var b = types.builders;
  12. recast.run(function(ast, callback) {
  13. recast.visit(ast, {
  14. visitForStatement: function(path) {
  15. var fst = path.node;
  16. path.replace(
  17. fst.init,
  18. b.whileStatement(
  19. fst.test,
  20. insertBeforeLoopback(fst, fst.update)
  21. )
  22. );
  23. this.traverse(path);
  24. },
  25. visitDoWhileStatement: function(path) {
  26. var dwst = path.node;
  27. return b.whileStatement(
  28. b.literal(true),
  29. insertBeforeLoopback(
  30. dwst,
  31. b.ifStatement(
  32. dwst.test,
  33. b.breakStatement()
  34. )
  35. )
  36. );
  37. }
  38. });
  39. callback(ast);
  40. });
  41. function insertBeforeLoopback(loop, toInsert) {
  42. var body = loop.body;
  43. if (!n.Statement.check(toInsert)) {
  44. toInsert = b.expressionStatement(toInsert);
  45. }
  46. if (n.BlockStatement.check(body)) {
  47. body.body.push(toInsert);
  48. } else {
  49. body = b.blockStatement([body, toInsert]);
  50. loop.body = body;
  51. }
  52. recast.visit(body, {
  53. visitContinueStatement: function(path) {
  54. var cst = path.node;
  55. assert.equal(
  56. cst.label, null,
  57. "Labeled continue statements are not yet supported."
  58. );
  59. path.replace(toInsert, path.node);
  60. return false;
  61. },
  62. // Do not descend into nested loops.
  63. visitWhileStatement: function() {},
  64. visitForStatement: function() {},
  65. visitForInStatement: function() {},
  66. visitDoWhileStatement: function() {}
  67. });
  68. return body;
  69. }