squeeze-more.js 3.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. var jsp = require("./parse-js"),
  2. pro = require("./process"),
  3. slice = jsp.slice,
  4. member = jsp.member,
  5. curry = jsp.curry,
  6. MAP = pro.MAP,
  7. PRECEDENCE = jsp.PRECEDENCE,
  8. OPERATORS = jsp.OPERATORS;
  9. function ast_squeeze_more(ast) {
  10. var w = pro.ast_walker(), walk = w.walk, scope;
  11. function with_scope(s, cont) {
  12. var save = scope, ret;
  13. scope = s;
  14. ret = cont();
  15. scope = save;
  16. return ret;
  17. };
  18. function _lambda(name, args, body) {
  19. return [ this[0], name, args, with_scope(body.scope, curry(MAP, body, walk)) ];
  20. };
  21. return w.with_walkers({
  22. "toplevel": function(body) {
  23. return [ this[0], with_scope(this.scope, curry(MAP, body, walk)) ];
  24. },
  25. "function": _lambda,
  26. "defun": _lambda,
  27. "new": function(ctor, args) {
  28. if (ctor[0] == "name") {
  29. if (ctor[1] == "Array" && !scope.has("Array")) {
  30. if (args.length != 1) {
  31. return [ "array", args ];
  32. } else {
  33. return walk([ "call", [ "name", "Array" ], args ]);
  34. }
  35. } else if (ctor[1] == "Object" && !scope.has("Object")) {
  36. if (!args.length) {
  37. return [ "object", [] ];
  38. } else {
  39. return walk([ "call", [ "name", "Object" ], args ]);
  40. }
  41. } else if ((ctor[1] == "RegExp" || ctor[1] == "Function" || ctor[1] == "Error") && !scope.has(ctor[1])) {
  42. return walk([ "call", [ "name", ctor[1] ], args]);
  43. }
  44. }
  45. },
  46. "call": function(expr, args) {
  47. if (expr[0] == "dot" && expr[1][0] == "string" && args.length == 1
  48. && (args[0][1] > 0 && expr[2] == "substring" || expr[2] == "substr")) {
  49. return [ "call", [ "dot", expr[1], "slice"], args];
  50. }
  51. if (expr[0] == "dot" && expr[2] == "toString" && args.length == 0) {
  52. // foo.toString() ==> foo+""
  53. if (expr[1][0] == "string") return expr[1];
  54. return [ "binary", "+", expr[1], [ "string", "" ]];
  55. }
  56. if (expr[0] == "name") {
  57. if (expr[1] == "Array" && args.length != 1 && !scope.has("Array")) {
  58. return [ "array", args ];
  59. }
  60. if (expr[1] == "Object" && !args.length && !scope.has("Object")) {
  61. return [ "object", [] ];
  62. }
  63. if (expr[1] == "String" && !scope.has("String")) {
  64. return [ "binary", "+", args[0], [ "string", "" ]];
  65. }
  66. }
  67. }
  68. }, function() {
  69. return walk(pro.ast_add_scope(ast));
  70. });
  71. };
  72. exports.ast_squeeze_more = ast_squeeze_more;
  73. // Local variables:
  74. // js-indent-level: 8
  75. // End: