Index: scripts/decompile.js |
diff --git a/scripts/decompile.js b/scripts/decompile.js |
deleted file mode 100644 |
index 250ae2afb74ce55523cfd2edfd979014108d136e..0000000000000000000000000000000000000000 |
--- a/scripts/decompile.js |
+++ /dev/null |
@@ -1,454 +0,0 @@ |
-// Decompile a JS file. This will be painful. |
-include("../utils/dumpast.js"); |
-include("../utils/astml.js"); |
- |
-let visitor = { |
- _visitArray: function (arr, pre, post, comma) { |
- if (pre === undefined) pre = '('; |
- if (post === undefined) post = ')'; |
- if (comma === undefined) comma = ', '; |
- output(pre); |
- for each (let arg in arr) { |
- arg.visit(this); |
- output(comma); |
- } |
- if (arr.length > 0) |
- unwrite(comma.length); |
- output(post); |
- }, |
- _visitMaybeBlock: function (body) { |
- if (body.type == "BlockStatement") { |
- output(" "); |
- body.visit(this); |
- } else { |
- flush().indent(); |
- body.visit(this); |
- unindent(); |
- } |
- }, |
- _visitNeedBlock: function (stmt, noFlush) { |
- if (stmt.type == "EmptyStatement") { |
- output("{}") |
- if (!noFlush) |
- flush(); |
- } |
- else if (stmt.type == "ReturnStatement") { |
- output("{").flush().indent(); |
- stmt.visit(this); |
- unindent().output("}"); |
- if (!noFlush) |
- flush(); |
- } |
- else |
- stmt.visit(this); |
- }, |
- visitProgram: function (program) {}, |
- visitFunctionDeclaration: function (func) { |
- output("function "); |
- if (func.name) |
- output(func.name); |
- this._visitArray(func.arguments, '(', ') '); |
- this._visitNeedBlock(func.body, true); |
- return true; |
- }, |
- visitParameter: function (p) { |
- output(p.name); |
- }, |
- visitBlockStatement: function (stmt) { |
- output("{").flush().indent(); |
- }, |
- postvisitBlockStatement: function (stmt) { |
- output("}").unindent().flush(); |
- }, |
- visitVarStatement: function (stmt) { |
- output(stmt.vartype).output(" "); |
- this._visitArray(stmt.variables, '', ''); |
- if (!this._noFlush) |
- output(';').flush(); |
- this._noFlush = false; |
- return true; |
- }, |
- visitVarDeclaration: function (decl) { |
- output(decl.name); |
- if ("initializer" in decl) |
- output(" = "); |
- }, |
- visitLetStatement: function (stmt) { |
- output("let "); |
- this._visitArray(stmt.variables, '(', ')'); |
- if (!this._noFlush) |
- output(';').flush(); |
- this._noFlush = false; |
- return true; |
- }, |
- visitExpressionStatement: function (stmt) {}, |
- postvisitExpressionStatement: function (stmt) { |
- output(";").flush(); |
- }, |
- visitEmptyStatement: function (stmt) { output(";").flush(); }, |
- visitIfStatement: function (stmt) { |
- output("if ("); |
- stmt.cond.visit(this); |
- output(")"); |
- this._visitMaybeBlock(stmt.body); |
- if (stmt.elsebody) { |
- output(" else"); |
- this._visitMaybeBlock(stmt.elsebody); |
- } |
- return true; |
- }, |
- visitDoWhileStatement: function (stmt) { |
- output("do"); |
- this._visitMaybeBlock(stmt.body); |
- output("while ("); |
- stmt.cond.visit(this); |
- output(");").flush(); |
- return true; |
- }, |
- visitWhileStatement: function (stmt) { |
- output("while ("); |
- stmt.cond.visit(this); |
- output(")"); |
- this._visitMaybeBlock(stmt.body); |
- return true; |
- }, |
- visitForStatement: function (stmt) { |
- output("for ("); |
- stmt.init.visit(this); |
- stmt.cond.visit(this); |
- if (stmt.cond.type != "EmptyStatement") |
- output("; "); |
- stmt.inc.visit(this); |
- output(")"); |
- this._visitMaybeBlock(stmt.body); |
- return true; |
- }, |
- visitForInStatement: function (stmt) { |
- output(stmt.itertype).output(" ("); |
- this._noFlush = true; |
- stmt.itervar.visit(this); |
- output(" in "); |
- stmt.iterrange.visit(this); |
- output(")"); |
- this._visitMaybeBlock(stmt.body); |
- return true; |
- }, |
- visitContinueStatement: function (stmt) { |
- output("continue"); |
- if ("label" in stmt) |
- output(" ").output(stmt.label); |
- output(";").flush(); |
- }, |
- visitBreakStatement: function (stmt) { |
- output("break"); |
- if ("label" in stmt) |
- output(" ").output(stmt.label); |
- output(";").flush(); |
- }, |
- visitReturnStatement: function (stmt) { output("return "); }, |
- postvisitReturnStatement: function (stmt) { output(";").flush(); }, |
- visitWithStatement: function (stmt) { |
- output("with ("); |
- stmt.variable.visit(this); |
- output(")"); |
- this._visitMaybeBlock(stmt.body); |
- return true; |
- }, |
- visitLabeledStatement: function (stmt) { output(stmt.label).output(": "); }, |
- visitSwitchStatement: function (stmt) { |
- output("switch ("); |
- stmt.expr.visit(this); |
- output(") {").flush().indent(); |
- this._visitArray(stmt.cases, '', '', ''); |
- output("}").unindent().flush(); |
- return true; |
- }, |
- visitSwitchCase: function (stmt) { |
- if ("expr" in stmt) { |
- output("case "); |
- stmt.expr.visit(this); |
- output(": "); |
- } else |
- output("default: "); |
- stmt.body.visit(this); |
- return true; |
- }, |
- visitThrowStatement: function (stmt) { output("throw "); }, |
- postvisitThrowStatement: function (stmt) { output(";").flush(); }, |
- visitTryStatement: function (stmt) { |
- output("try "); |
- this._visitNeedBlock(stmt.body); |
- this._visitArray(stmt.catchers, '', '', '\n' + indentStr); |
- if (stmt.fin) { |
- output("finally "); |
- this._visitNeedBlock(stmt.fin); |
- } |
- return true; |
- }, |
- visitCatchStatement: function (stmt) { |
- output("catch ("); |
- stmt.variable.visit(this); |
- if ("cond" in stmt) { |
- output(" if "); |
- stmt.cond.visit(this); |
- } |
- output(")"); |
- this._visitNeedBlock(stmt.body); |
- return true; |
- }, |
- visitDebuggerStatement: function (stmt) { output("debugger;").flush(); }, |
- |
- visitThisExpression: function (expr) { output("this"); }, |
- visitMemberExpression: function (expr) { |
- let needparen = expr.precedence + 1 < expr.container.precedence; |
- if (needparen) |
- output("("); |
- expr.container.visit(this); |
- if (needparen) |
- output(")"); |
- |
- if ("constmember" in expr && /^[_a-zA-Z]\w*$/.test(expr.constmember)) |
- output(".").output(expr.constmember); |
- else { |
- output("["); |
- expr.member.visit(this); |
- output("]"); |
- } |
- return true; |
- }, |
- visitNewExpression: function (expr) { |
- let needparen = expr.precedence < expr.constructor.precedence; |
- output("new "); |
- if (needparen) |
- output("("); |
- expr.constructor.visit(this); |
- if (needparen) |
- output(")"); |
- this._visitArray(expr.arguments); |
- return true; |
- }, |
- visitCallExpression: function (expr) { |
- let needparen = expr.precedence < expr.func.precedence; |
- if (needparen) |
- output("("); |
- expr.func.visit(this); |
- if (needparen) |
- output(")"); |
- this._visitArray(expr.arguments); |
- return true; |
- }, |
- visitLiteralExpression: function (expr) { |
- switch (expr.objtype) { |
- case "string": |
- output('"').output(sanitize(expr.value, '"')).output('"'); |
- break; |
- case "number": |
- case "boolean": |
- case "regex": |
- output(expr.value.toString()); |
- break; |
- case "null": |
- output("null"); |
- break; |
- default: |
- throw "Unknown literal " + expr.objtype; |
- }; |
- }, |
- visitObjectLiteral: function (obj) { |
- output('{').flush().indent(); |
- this._visitArray(obj.setters, '', '', ',\n' + indentStr); |
- flush().output('}').unindent(); |
- return true; |
- }, |
- visitPropertyLiteral: function (prop) { |
- if ("proptype" in prop) { |
- if (prop.value.type == "LiteralExpression") { |
- prop.property.visit(this); |
- output(" ").output(prop.proptype).output(": "); |
- prop.value.visit(this); |
- return true; |
- } |
- if (prop.proptype == "getter") |
- output("get "); |
- else if (prop.proptype == "setter") |
- output("set "); |
- else |
- throw "Unknown type: " + prop.proptype; |
- prop.property.visit(this); |
- if (prop.value.type != "FunctionDeclaration") |
- throw "Expection function, found: " + prop.value.type; |
- if (prop.value.name) { |
- output(" ").output(prop.value.name); |
- } |
- this._visitArray(prop.value.arguments, '(', ') '); |
- this._visitNeedBlock(prop.value.body, true); |
- return true; |
- } |
- prop.property.visit(this); |
- output(": "); |
- prop.value.visit(this); |
- return true; |
- }, |
- visitArrayLiteral: function (arr) { |
- this._visitArray(arr.members, '[', ']', ', '); |
- return true; |
- }, |
- visitArrayComprehensionExpression: function (arrcomp) { |
- output('['); |
- let enp = arrcomp.element.precedence > 16; |
- if (enp) |
- output("("); |
- arrcomp.element.visit(this); |
- if (enp) |
- output(")"); |
- output(" ").output(arrcomp.itertype).output("("); |
- arrcomp.itervar.visit(this); |
- output(" in "); |
- arrcomp.iterrange.visit(this); |
- output(")"); |
- if ("iterif" in arrcomp) { |
- output(" if ("); |
- arrcomp.iterif.visit(this); |
- output(")"); |
- } |
- output("]"); |
- return true; |
- }, |
- visitIdentifierExpression: function (expr) { |
- output(expr.name); |
- if ("initializer" in expr) { |
- output(" = "); |
- expr.initializer.visit(this); |
- return true; |
- } |
- }, |
- visitPostfixExpression: function (expr) {}, |
- postvisitPostfixExpression: function (expr) { |
- output(expr.operator); |
- }, |
- visitUnaryExpression: function (expr) { |
- if (expr.operator != '()') { |
- output(expr.operator); |
- if (expr.operator.length > 1) |
- output(" "); |
- } |
- let np = expr.precedence < expr.operand.precedence; |
- if (expr.operator == '()' || np) { |
- output("("); |
- expr.operand.visit(this); |
- output(")"); |
- return true; |
- } |
- }, |
- visitBinaryExpression: function (expr) { |
- let lhp = expr.precedence < expr.lhs.precedence; |
- let rhp = expr.precedence < expr.rhs.precedence; |
- if (lhp) |
- output("("); |
- expr.lhs.visit(this); |
- if (lhp) |
- output(")"); |
- output(" ").output(expr.operator).output(" "); |
- if (rhp) |
- output("("); |
- expr.rhs.visit(this); |
- if (rhp) |
- output(")"); |
- return true; |
- }, |
- visitConditionalExpression: function (expr) { |
- let lhp = expr.precedence < expr.cond.precedence; |
- let mhp = expr.precedence < expr.iftrue.precedence; |
- let rhp = expr.precedence < expr.iffalse.precedence; |
- if (lhp) |
- output("("); |
- expr.cond.visit(this); |
- if (lhp) |
- output(")"); |
- output(" ? "); |
- if (mhp) |
- output("("); |
- expr.iftrue.visit(this); |
- if (mhp) |
- output(")"); |
- output(" : "); |
- if (rhp) |
- output("("); |
- expr.iffalse.visit(this); |
- if (rhp) |
- output(")"); |
- return true; |
- }, |
- visitAssignmentExpression: function (expr) { |
- let lhp = expr.precedence < expr.lhs.precedence; |
- let rhp = expr.precedence < expr.rhs.precedence; |
- if (lhp) |
- output("("); |
- expr.lhs.visit(this); |
- if (lhp) |
- output(")"); |
- output(" ").output(expr.operator).output("= "); |
- if (rhp) |
- output("("); |
- expr.rhs.visit(this); |
- if (rhp) |
- output(")"); |
- return true; |
- }, |
-}; |
- |
-/* Reminder */ |
-for (let f in structure) { |
- if (!("visit" + f in visitor)) |
- throw "Please visit " + f; |
-} |
- |
-function process_js(ast) { |
- if (!ast) |
- return; |
- ast = makeAST(ast); |
- walkAST(ast, visitor); |
-} |
- |
-/* Output functions */ |
-let buffer = "", indentStr = ""; |
-function output(str) { |
- buffer += str; |
- return global; |
-} |
-function unwrite(numChars) { |
- buffer = buffer.substring(0, buffer.length - numChars); |
- return global; |
-} |
-function flush() { |
- _print(buffer); |
- buffer = indentStr; |
- return global; |
-} |
-function indent() { |
- indentStr += " "; |
- buffer = " " + buffer; |
- return global; |
-} |
-function unindent() { |
- indentStr = indentStr.substring(2); |
- buffer = buffer.substring(2); |
- return global; |
-} |
- |
-function sanitize(str, q) { |
- function replace(x) { |
- if (x == q) return '\\' + q; |
- if (x == '\\') return '\\\\'; |
- if (x == '\b') return '\\b'; |
- if (x == '\f') return '\\f'; |
- if (x == '\n') return '\\n'; |
- if (x == '\r') return '\\r'; |
- if (x == '\t') return '\\t'; |
- if (x == '\v') return '\\v'; |
- let val = x.charCodeAt(0) |
- if (x < ' ') return '\\x' + (val - val % 16) / 16 + (val % 16); |
- return x; |
- } |
- return [replace(x) for each (x in str)].join(''); |
-} |