diff --git a/demo.cola b/demo.cola new file mode 100644 index 00000000..0650190d --- /dev/null +++ b/demo.cola @@ -0,0 +1,32 @@ +function main(){ + console.log(` + + Hello! + My name is ColaScript, and i know who you are }:-> + @{navigator.userAgent} + + `); + + console.log("pow:", 5 ** 2, "; modulo:", 5 %% 3, ";"); + + var a = 3.14, b = 584; + + a ?= b; console.log(a); + a = undefined; + a ?= b; console.log(a); + + console.log(`is:`, location.href is String, `; isnt:`, 123 isnt Number, ";"); + + if(yes === true && on === true && no === false && off === false) console.log('Boolean alternatives'); + + console.log('Raw string:', r`@test \n \t \r`); + var isEmail = / + ([\w-\.]+) + @ + ((?:[\w]+\.)+) + ([a-zA-Z]{2,4}) + /, email = r'danon0404@gmail.com'; + console.log("@email is email:", isEmail.test(email)); +} + +main(); \ No newline at end of file diff --git a/lib/ast.js b/lib/ast.js index 6366162a..51ed69c3 100644 --- a/lib/ast.js +++ b/lib/ast.js @@ -45,9 +45,10 @@ ***********************************************************************/ "use strict"; +!window.Cola && (window.Cola = {}); -function DEFNODE(type, props, methods, base) { - if (arguments.length < 4) base = AST_Node; +Cola.DEFNODE = function (type, props, methods, base) { + if (arguments.length < 4) base = Cola.AST_Node; if (!props) props = []; else props = props.split(/\s+/); var self_props = props; @@ -87,10 +88,10 @@ function DEFNODE(type, props, methods, base) { return ctor; }; -var AST_Token = DEFNODE("Token", "type value line col pos endpos nlb comments_before file" /* ColaScropt + " endcol endline"*/, { +Cola.AST_Token = Cola.DEFNODE("Token", "type value line col pos endpos nlb comments_before file", { }, null); -var AST_Node = DEFNODE("Node", "start end", { +Cola.AST_Node = Cola.DEFNODE("Node", "start end", { clone: function() { return new this.CTOR(this); }, @@ -107,44 +108,44 @@ var AST_Node = DEFNODE("Node", "start end", { } }, null); -AST_Node.warn_function = null; -AST_Node.warn = function(txt, props) { - if (AST_Node.warn_function) - AST_Node.warn_function(string_template(txt, props)); +Cola.AST_Node.warn_function = null; +Cola.AST_Node.warn = function(txt, props) { + if (Cola.AST_Node.warn_function) + Cola.AST_Node.warn_function(Cola.string_template(txt, props)); }; /* -----[ statements ]----- */ -var AST_Statement = DEFNODE("Statement", null, { +Cola.AST_Statement = Cola.DEFNODE("Statement", null, { $documentation: "Base class of all statements", }); -var AST_Debugger = DEFNODE("Debugger", null, { +Cola.AST_Debugger = Cola.DEFNODE("Debugger", null, { $documentation: "Represents a debugger statement", -}, AST_Statement); +}, Cola.AST_Statement); -var AST_Directive = DEFNODE("Directive", "value scope", { +Cola.AST_Directive = Cola.DEFNODE("Directive", "value scope", { $documentation: "Represents a directive, like \"use strict\";", $propdoc: { value: "[string] The value of this directive as a plain string (it's not an AST_String!)", scope: "[AST_Scope/S] The scope that this directive affects" }, -}, AST_Statement); +}, Cola.AST_Statement); -var AST_SimpleStatement = DEFNODE("SimpleStatement", "body", { +Cola.AST_SimpleStatement = Cola.DEFNODE("SimpleStatement", "body", { $documentation: "A statement consisting of an expression, i.e. a = 1 + 2", $propdoc: { - body: "[AST_Node] an expression node (should not be instanceof AST_Statement)" + body: "[AST_Node] an expression node (should not be instanceof Cola.AST_Statement)" }, _walk: function(visitor) { return visitor._visit(this, function(){ this.body._walk(visitor); }); } -}, AST_Statement); +}, Cola.AST_Statement); -function walk_body(node, visitor) { - if (node.body instanceof AST_Statement) { +Cola.walk_body = function (node, visitor) { + if (node.body instanceof Cola.AST_Statement) { node.body._walk(visitor); } else node.body.forEach(function(stat){ @@ -152,30 +153,30 @@ function walk_body(node, visitor) { }); }; -var AST_Block = DEFNODE("Block", "body", { +Cola.AST_Block = Cola.DEFNODE("Block", "body", { $documentation: "A body of statements (usually bracketed)", $propdoc: { body: "[AST_Statement*] an array of statements" }, _walk: function(visitor) { return visitor._visit(this, function(){ - walk_body(this, visitor); + Cola.walk_body(this, visitor); }); } -}, AST_Statement); +}, Cola.AST_Statement); -var AST_BlockStatement = DEFNODE("BlockStatement", null, { +Cola.AST_BlockStatement = Cola.DEFNODE("BlockStatement", null, { $documentation: "A block statement", -}, AST_Block); +}, Cola.AST_Block); -var AST_EmptyStatement = DEFNODE("EmptyStatement", null, { +Cola.AST_EmptyStatement = Cola.DEFNODE("EmptyStatement", null, { $documentation: "The empty statement (empty block or simply a semicolon)", _walk: function(visitor) { return visitor._visit(this); } -}, AST_Statement); +}, Cola.AST_Statement); -var AST_StatementWithBody = DEFNODE("StatementWithBody", "body", { +Cola.AST_StatementWithBody = Cola.DEFNODE("StatementWithBody", "body", { $documentation: "Base class for all statements that contain one nested body: `For`, `ForIn`, `Do`, `While`, `With`", $propdoc: { body: "[AST_Statement] the body; this should always be present, even if it's an AST_EmptyStatement" @@ -185,9 +186,9 @@ var AST_StatementWithBody = DEFNODE("StatementWithBody", "body", { this.body._walk(visitor); }); } -}, AST_Statement); +}, Cola.AST_Statement); -var AST_LabeledStatement = DEFNODE("LabeledStatement", "label", { +Cola.AST_LabeledStatement = Cola.DEFNODE("LabeledStatement", "label", { $documentation: "Statement with a label", $propdoc: { label: "[AST_Label] a label definition" @@ -198,16 +199,16 @@ var AST_LabeledStatement = DEFNODE("LabeledStatement", "label", { this.body._walk(visitor); }); } -}, AST_StatementWithBody); +}, Cola.AST_StatementWithBody); -var AST_IterationStatement = DEFNODE("IterationStatement", null, { +Cola.AST_IterationStatement = Cola.DEFNODE("IterationStatement", null, { $documentation: "Internal class. All loops inherit from it." -}, AST_StatementWithBody); +}, Cola.AST_StatementWithBody); -var AST_DWLoop = DEFNODE("DWLoop", "condition", { +Cola.AST_DWLoop = Cola.DEFNODE("DWLoop", "condition", { $documentation: "Base class for do/while statements", $propdoc: { - condition: "[AST_Node] the loop condition. Should not be instanceof AST_Statement" + condition: "[AST_Node] the loop condition. Should not be instanceof Cola.AST_Statement" }, _walk: function(visitor) { return visitor._visit(this, function(){ @@ -215,17 +216,17 @@ var AST_DWLoop = DEFNODE("DWLoop", "condition", { this.body._walk(visitor); }); } -}, AST_IterationStatement); +}, Cola.AST_IterationStatement); -var AST_Do = DEFNODE("Do", null, { +Cola.AST_Do = Cola.DEFNODE("Do", null, { $documentation: "A `do` statement", -}, AST_DWLoop); +}, Cola.AST_DWLoop); -var AST_While = DEFNODE("While", null, { +Cola.AST_While = Cola.DEFNODE("While", null, { $documentation: "A `while` statement", -}, AST_DWLoop); +}, Cola.AST_DWLoop); -var AST_For = DEFNODE("For", "init condition step", { +Cola.AST_For = Cola.DEFNODE("For", "init condition step", { $documentation: "A `for` statement", $propdoc: { init: "[AST_Node?] the `for` initialization code, or null if empty", @@ -240,9 +241,9 @@ var AST_For = DEFNODE("For", "init condition step", { this.body._walk(visitor); }); } -}, AST_IterationStatement); +}, Cola.AST_IterationStatement); -var AST_ForIn = DEFNODE("ForIn", "init name object", { +Cola.AST_ForIn = Cola.DEFNODE("ForIn", "init name object", { $documentation: "A `for ... in` statement", $propdoc: { init: "[AST_Node] the `for/in` initialization code", @@ -256,9 +257,9 @@ var AST_ForIn = DEFNODE("ForIn", "init name object", { this.body._walk(visitor); }); } -}, AST_IterationStatement); +}, Cola.AST_IterationStatement); -var AST_With = DEFNODE("With", "expression", { +Cola.AST_With = Cola.DEFNODE("With", "expression", { $documentation: "A `with` statement", $propdoc: { expression: "[AST_Node] the `with` expression" @@ -269,11 +270,11 @@ var AST_With = DEFNODE("With", "expression", { this.body._walk(visitor); }); } -}, AST_StatementWithBody); +}, Cola.AST_StatementWithBody); /* -----[ scope and functions ]----- */ -var AST_Scope = DEFNODE("Scope", "directives variables functions uses_with uses_eval parent_scope enclosed cname", { +Cola.AST_Scope = Cola.DEFNODE("Scope", "directives variables functions uses_with uses_eval parent_scope enclosed cname", { $documentation: "Base class for all statements introducing a lexical scope", $propdoc: { directives: "[string*/S] an array of directives declared in this scope", @@ -285,9 +286,9 @@ var AST_Scope = DEFNODE("Scope", "directives variables functions uses_with uses_ enclosed: "[SymbolDef*/S] a list of all symbol definitions that are accessed from this scope or any subscopes", cname: "[integer/S] current index for mangling variables (used internally by the mangler)", }, -}, AST_Block); +}, Cola.AST_Block); -var AST_Toplevel = DEFNODE("Toplevel", "globals", { +Cola.AST_Toplevel = Cola.DEFNODE("Toplevel", "globals", { $documentation: "The toplevel scope", $propdoc: { globals: "[Object/S] a map of name -> SymbolDef for all undeclared names", @@ -305,10 +306,10 @@ var AST_Toplevel = DEFNODE("Toplevel", "globals", { }); var wrapped_tl = "(function(" + parameters.join(",") + "){ '$ORIG'; })(" + args.join(",") + ")"; - wrapped_tl = parse(wrapped_tl); + wrapped_tl = Cola.parse(wrapped_tl); wrapped_tl = wrapped_tl.transform(new TreeTransformer(function before(node){ - if (node instanceof AST_Directive && node.value == "$ORIG") { - return MAP.splice(self.body); + if (node instanceof Cola.AST_Directive && node.value == "$ORIG") { + return Cola.MAP.splice(self.body); } })); return wrapped_tl; @@ -319,43 +320,43 @@ var AST_Toplevel = DEFNODE("Toplevel", "globals", { if (export_all) { self.figure_out_scope(); self.walk(new TreeWalker(function(node){ - if (node instanceof AST_SymbolDeclaration && node.definition().global) { - if (!find_if(function(n){ return n.name == node.name }, to_export)) + if (node instanceof Cola.AST_SymbolDeclaration && node.definition().global) { + if (!Cola.find_if(function(n){ return n.name == node.name }, to_export)) to_export.push(node); } })); } var wrapped_tl = "(function(exports, global){ global['" + name + "'] = exports; '$ORIG'; '$EXPORTS'; }({}, (function(){return this}())))"; - wrapped_tl = parse(wrapped_tl); + wrapped_tl = Cola.parse(wrapped_tl); wrapped_tl = wrapped_tl.transform(new TreeTransformer(function before(node){ - if (node instanceof AST_SimpleStatement) { + if (node instanceof Cola.AST_SimpleStatement) { node = node.body; - if (node instanceof AST_String) switch (node.getValue()) { + if (node instanceof Cola.AST_String) switch (node.getValue()) { case "$ORIG": - return MAP.splice(self.body); + return Cola.MAP.splice(self.body); case "$EXPORTS": var body = []; to_export.forEach(function(sym){ - body.push(new AST_SimpleStatement({ - body: new AST_Assign({ - left: new AST_Sub({ - expression: new AST_SymbolRef({ name: "exports" }), - property: new AST_String({ value: sym.name }), + body.push(new Cola.AST_SimpleStatement({ + body: new Cola.AST_Assign({ + left: new Cola.AST_Sub({ + expression: new Cola.AST_SymbolRef({ name: "exports" }), + property: new Cola.AST_String({ value: sym.name }), }), operator: "=", - right: new AST_SymbolRef(sym), + right: new Cola.AST_SymbolRef(sym), }), })); }); - return MAP.splice(body); + return Cola.MAP.splice(body); } } })); return wrapped_tl; } -}, AST_Scope); +}, Cola.AST_Scope); -var AST_Lambda = DEFNODE("Lambda", "name argnames uses_arguments", { +Cola.AST_Lambda = Cola.DEFNODE("Lambda", "name argnames uses_arguments", { $documentation: "Base class for functions", $propdoc: { name: "[AST_SymbolDeclaration?] the name of this function", @@ -368,30 +369,30 @@ var AST_Lambda = DEFNODE("Lambda", "name argnames uses_arguments", { this.argnames.forEach(function(arg){ arg._walk(visitor); }); - walk_body(this, visitor); + Cola.walk_body(this, visitor); }); } -}, AST_Scope); +}, Cola.AST_Scope); -var AST_Accessor = DEFNODE("Accessor", null, { +Cola.AST_Accessor = Cola.DEFNODE("Accessor", null, { $documentation: "A setter/getter function. The `name` property is always null." -}, AST_Lambda); +}, Cola.AST_Lambda); -var AST_Function = DEFNODE("Function", null, { +Cola.AST_Function = Cola.DEFNODE("Function", null, { $documentation: "A function expression" -}, AST_Lambda); +}, Cola.AST_Lambda); -var AST_Defun = DEFNODE("Defun", null, { +Cola.AST_Defun = Cola.DEFNODE("Defun", null, { $documentation: "A function definition" -}, AST_Lambda); +}, Cola.AST_Lambda); /* -----[ JUMPS ]----- */ -var AST_Jump = DEFNODE("Jump", null, { +Cola.AST_Jump = Cola.DEFNODE("Jump", null, { $documentation: "Base class for “jumps” (for now that's `return`, `throw`, `break` and `continue`)" -}, AST_Statement); +}, Cola.AST_Statement); -var AST_Exit = DEFNODE("Exit", "value", { +Cola.AST_Exit = Cola.DEFNODE("Exit", "value", { $documentation: "Base class for “exits” (`return` and `throw`)", $propdoc: { value: "[AST_Node?] the value returned or thrown by this statement; could be null for AST_Return" @@ -401,17 +402,17 @@ var AST_Exit = DEFNODE("Exit", "value", { this.value._walk(visitor); }); } -}, AST_Jump); +}, Cola.AST_Jump); -var AST_Return = DEFNODE("Return", null, { +Cola.AST_Return = Cola.DEFNODE("Return", null, { $documentation: "A `return` statement" -}, AST_Exit); +}, Cola.AST_Exit); -var AST_Throw = DEFNODE("Throw", null, { +Cola.AST_Throw = Cola.DEFNODE("Throw", null, { $documentation: "A `throw` statement" -}, AST_Exit); +}, Cola.AST_Exit); -var AST_LoopControl = DEFNODE("LoopControl", "label", { +Cola.AST_LoopControl = Cola.DEFNODE("LoopControl", "label", { $documentation: "Base class for loop control statements (`break` and `continue`)", $propdoc: { label: "[AST_LabelRef?] the label, or null if none", @@ -421,19 +422,19 @@ var AST_LoopControl = DEFNODE("LoopControl", "label", { this.label._walk(visitor); }); } -}, AST_Jump); +}, Cola.AST_Jump); -var AST_Break = DEFNODE("Break", null, { +Cola.AST_Break = Cola.DEFNODE("Break", null, { $documentation: "A `break` statement" -}, AST_LoopControl); +}, Cola.AST_LoopControl); -var AST_Continue = DEFNODE("Continue", null, { +Cola.AST_Continue = Cola.DEFNODE("Continue", null, { $documentation: "A `continue` statement" -}, AST_LoopControl); +}, Cola.AST_LoopControl); /* -----[ IF ]----- */ -var AST_If = DEFNODE("If", "condition alternative", { +Cola.AST_If = Cola.DEFNODE("If", "condition alternative", { $documentation: "A `if` statement", $propdoc: { condition: "[AST_Node] the `if` condition", @@ -446,11 +447,11 @@ var AST_If = DEFNODE("If", "condition alternative", { if (this.alternative) this.alternative._walk(visitor); }); } -}, AST_StatementWithBody); +}, Cola.AST_StatementWithBody); /* -----[ SWITCH ]----- */ -var AST_Switch = DEFNODE("Switch", "expression", { +Cola.AST_Switch = Cola.DEFNODE("Switch", "expression", { $documentation: "A `switch` statement", $propdoc: { expression: "[AST_Node] the `switch` “discriminant”" @@ -458,20 +459,20 @@ var AST_Switch = DEFNODE("Switch", "expression", { _walk: function(visitor) { return visitor._visit(this, function(){ this.expression._walk(visitor); - walk_body(this, visitor); + Cola.walk_body(this, visitor); }); } -}, AST_Block); +}, Cola.AST_Block); -var AST_SwitchBranch = DEFNODE("SwitchBranch", null, { +Cola.AST_SwitchBranch = Cola.DEFNODE("SwitchBranch", null, { $documentation: "Base class for `switch` branches", -}, AST_Block); +}, Cola.AST_Block); -var AST_Default = DEFNODE("Default", null, { +Cola.AST_Default = Cola.DEFNODE("Default", null, { $documentation: "A `default` switch branch", -}, AST_SwitchBranch); +}, Cola.AST_SwitchBranch); -var AST_Case = DEFNODE("Case", "expression", { +Cola.AST_Case = Cola.DEFNODE("Case", "expression", { $documentation: "A `case` switch branch", $propdoc: { expression: "[AST_Node] the `case` expression" @@ -479,14 +480,14 @@ var AST_Case = DEFNODE("Case", "expression", { _walk: function(visitor) { return visitor._visit(this, function(){ this.expression._walk(visitor); - walk_body(this, visitor); + Cola.walk_body(this, visitor); }); } -}, AST_SwitchBranch); +}, Cola.AST_SwitchBranch); /* -----[ EXCEPTIONS ]----- */ -var AST_Try = DEFNODE("Try", "bcatch bfinally", { +Cola.AST_Try = Cola.DEFNODE("Try", "bcatch bfinally", { $documentation: "A `try` statement", $propdoc: { bcatch: "[AST_Catch?] the catch block, or null if not present", @@ -494,14 +495,14 @@ var AST_Try = DEFNODE("Try", "bcatch bfinally", { }, _walk: function(visitor) { return visitor._visit(this, function(){ - walk_body(this, visitor); + Cola.walk_body(this, visitor); if (this.bcatch) this.bcatch._walk(visitor); if (this.bfinally) this.bfinally._walk(visitor); }); } -}, AST_Block); +}, Cola.AST_Block); -var AST_Catch = DEFNODE("Catch", "argname", { +Cola.AST_Catch = Cola.DEFNODE("Catch", "argname", { $documentation: "A `catch` node; only makes sense as part of a `try` statement", $propdoc: { argname: "[AST_SymbolCatch] symbol for the exception" @@ -509,18 +510,18 @@ var AST_Catch = DEFNODE("Catch", "argname", { _walk: function(visitor) { return visitor._visit(this, function(){ this.argname._walk(visitor); - walk_body(this, visitor); + Cola.walk_body(this, visitor); }); } -}, AST_Block); +}, Cola.AST_Block); -var AST_Finally = DEFNODE("Finally", null, { +Cola.AST_Finally = Cola.DEFNODE("Finally", null, { $documentation: "A `finally` node; only makes sense as part of a `try` statement" -}, AST_Block); +}, Cola.AST_Block); /* -----[ VAR/CONST ]----- */ -var AST_Definitions = DEFNODE("Definitions", "definitions", { +Cola.AST_Definitions = Cola.DEFNODE("Definitions", "definitions", { $documentation: "Base class for `var` or `const` nodes (variable declarations/initializations)", $propdoc: { definitions: "[AST_VarDef*] array of variable definitions" @@ -532,17 +533,17 @@ var AST_Definitions = DEFNODE("Definitions", "definitions", { }); }); } -}, AST_Statement); +}, Cola.AST_Statement); -var AST_Var = DEFNODE("Var", null, { +Cola.AST_Var = Cola.DEFNODE("Var", null, { $documentation: "A `var` statement" -}, AST_Definitions); +}, Cola.AST_Definitions); -var AST_Const = DEFNODE("Const", null, { +Cola.AST_Const = Cola.DEFNODE("Const", null, { $documentation: "A `const` statement" -}, AST_Definitions); +}, Cola.AST_Definitions); -var AST_VarDef = DEFNODE("VarDef", "name value", { +Cola.AST_VarDef = Cola.DEFNODE("VarDef", "name value", { $documentation: "A variable declaration; only appears in a AST_Definitions node", $propdoc: { name: "[AST_SymbolVar|AST_SymbolConst] name of the variable", @@ -558,7 +559,7 @@ var AST_VarDef = DEFNODE("VarDef", "name value", { /* -----[ OTHER ]----- */ -var AST_Call = DEFNODE("Call", "expression args", { +Cola.AST_Call = Cola.DEFNODE("Call", "expression args", { $documentation: "A function call expression", $propdoc: { expression: "[AST_Node] expression to invoke as function", @@ -574,18 +575,18 @@ var AST_Call = DEFNODE("Call", "expression args", { } }); -var AST_New = DEFNODE("New", null, { +Cola.AST_New = Cola.DEFNODE("New", null, { $documentation: "An object instantiation. Derives from a function call since it has exactly the same properties" -}, AST_Call); +}, Cola.AST_Call); -var AST_Seq = DEFNODE("Seq", "car cdr", { +Cola.AST_Seq = Cola.DEFNODE("Seq", "car cdr", { $documentation: "A sequence expression (two comma-separated expressions)", $propdoc: { car: "[AST_Node] first element in sequence", cdr: "[AST_Node] second element in sequence" }, $cons: function(x, y) { - var seq = new AST_Seq(x); + var seq = new Cola.AST_Seq(x); seq.car = x; seq.cdr = y; return seq; @@ -595,7 +596,7 @@ var AST_Seq = DEFNODE("Seq", "car cdr", { if (array.length == 1) return array[0].clone(); var list = null; for (var i = array.length; --i >= 0;) { - list = AST_Seq.cons(array[i], list); + list = Cola.AST_Seq.cons(array[i], list); } var p = list; while (p) { @@ -611,7 +612,7 @@ var AST_Seq = DEFNODE("Seq", "car cdr", { var p = this, a = []; while (p) { a.push(p.car); - if (p.cdr && !(p.cdr instanceof AST_Seq)) { + if (p.cdr && !(p.cdr instanceof Cola.AST_Seq)) { a.push(p.cdr); break; } @@ -622,8 +623,8 @@ var AST_Seq = DEFNODE("Seq", "car cdr", { add: function(node) { var p = this; while (p) { - if (!(p.cdr instanceof AST_Seq)) { - var cell = AST_Seq.cons(p.cdr, node); + if (!(p.cdr instanceof Cola.AST_Seq)) { + var cell = Cola.AST_Seq.cons(p.cdr, node); return p.cdr = cell; } p = p.cdr; @@ -637,7 +638,7 @@ var AST_Seq = DEFNODE("Seq", "car cdr", { } }); -var AST_PropAccess = DEFNODE("PropAccess", "expression property", { +Cola.AST_PropAccess = Cola.DEFNODE("PropAccess", "expression property", { $documentation: "Base class for property access expressions, i.e. `a.foo` or `a[\"foo\"]`", $propdoc: { expression: "[AST_Node] the “container” expression", @@ -645,16 +646,16 @@ var AST_PropAccess = DEFNODE("PropAccess", "expression property", { } }); -var AST_Dot = DEFNODE("Dot", null, { +Cola.AST_Dot = Cola.DEFNODE("Dot", null, { $documentation: "A dotted property access expression", _walk: function(visitor) { return visitor._visit(this, function(){ this.expression._walk(visitor); }); } -}, AST_PropAccess); +}, Cola.AST_PropAccess); -var AST_Sub = DEFNODE("Sub", null, { +Cola.AST_Sub = Cola.DEFNODE("Sub", null, { $documentation: "Index-style property access, i.e. `a[\"foo\"]`", _walk: function(visitor) { return visitor._visit(this, function(){ @@ -662,9 +663,9 @@ var AST_Sub = DEFNODE("Sub", null, { this.property._walk(visitor); }); } -}, AST_PropAccess); +}, Cola.AST_PropAccess); -var AST_Unary = DEFNODE("Unary", "operator expression", { +Cola.AST_Unary = Cola.DEFNODE("Unary", "operator expression", { $documentation: "Base class for unary expressions", $propdoc: { operator: "[string] the operator", @@ -677,15 +678,15 @@ var AST_Unary = DEFNODE("Unary", "operator expression", { } }); -var AST_UnaryPrefix = DEFNODE("UnaryPrefix", null, { +Cola.AST_UnaryPrefix = Cola.DEFNODE("UnaryPrefix", null, { $documentation: "Unary prefix expression, i.e. `typeof i` or `++i`" -}, AST_Unary); +}, Cola.AST_Unary); -var AST_UnaryPostfix = DEFNODE("UnaryPostfix", null, { +Cola.AST_UnaryPostfix = Cola.DEFNODE("UnaryPostfix", null, { $documentation: "Unary postfix expression, i.e. `i++`" -}, AST_Unary); +}, Cola.AST_Unary); -var AST_Binary = DEFNODE("Binary", "left operator right", { +Cola.AST_Binary = Cola.DEFNODE("Binary", "left operator right", { $documentation: "Binary expression, i.e. `a + b`", $propdoc: { left: "[AST_Node] left-hand side expression", @@ -700,7 +701,7 @@ var AST_Binary = DEFNODE("Binary", "left operator right", { } }); -var AST_Conditional = DEFNODE("Conditional", "condition consequent alternative", { +Cola.AST_Conditional = Cola.DEFNODE("Conditional", "condition consequent alternative", { $documentation: "Conditional expression using the ternary operator, i.e. `a ? b : c`", $propdoc: { condition: "[AST_Node]", @@ -716,13 +717,13 @@ var AST_Conditional = DEFNODE("Conditional", "condition consequent alternative", } }); -var AST_Assign = DEFNODE("Assign", null, { +Cola.AST_Assign = Cola.DEFNODE("Assign", null, { $documentation: "An assignment expression — `a = b + 5`", -}, AST_Binary); +}, Cola.AST_Binary); /* -----[ LITERALS ]----- */ -var AST_Array = DEFNODE("Array", "elements", { +Cola.AST_Array = Cola.DEFNODE("Array", "elements", { $documentation: "An array literal", $propdoc: { elements: "[AST_Node*] array of elements" @@ -736,7 +737,7 @@ var AST_Array = DEFNODE("Array", "elements", { } }); -var AST_Object = DEFNODE("Object", "properties", { +Cola.AST_Object = Cola.DEFNODE("Object", "properties", { $documentation: "An object literal", $propdoc: { properties: "[AST_ObjectProperty*] array of properties" @@ -750,7 +751,7 @@ var AST_Object = DEFNODE("Object", "properties", { } }); -var AST_ObjectProperty = DEFNODE("ObjectProperty", "key value", { +Cola.AST_ObjectProperty = Cola.DEFNODE("ObjectProperty", "key value", { $documentation: "Base class for literal object properties", $propdoc: { key: "[string] the property name converted to a string for ObjectKeyVal. For setters and getters this is an arbitrary AST_Node.", @@ -763,19 +764,19 @@ var AST_ObjectProperty = DEFNODE("ObjectProperty", "key value", { } }); -var AST_ObjectKeyVal = DEFNODE("ObjectKeyVal", null, { +Cola.AST_ObjectKeyVal = Cola.DEFNODE("ObjectKeyVal", null, { $documentation: "A key: value object property", -}, AST_ObjectProperty); +}, Cola.AST_ObjectProperty); -var AST_ObjectSetter = DEFNODE("ObjectSetter", null, { +Cola.AST_ObjectSetter = Cola.DEFNODE("ObjectSetter", null, { $documentation: "An object setter property", -}, AST_ObjectProperty); +}, Cola.AST_ObjectProperty); -var AST_ObjectGetter = DEFNODE("ObjectGetter", null, { +Cola.AST_ObjectGetter = Cola.DEFNODE("ObjectGetter", null, { $documentation: "An object getter property", -}, AST_ObjectProperty); +}, Cola.AST_ObjectProperty); -var AST_Symbol = DEFNODE("Symbol", "scope name thedef", { +Cola.AST_Symbol = Cola.DEFNODE("Symbol", "scope name thedef", { $propdoc: { name: "[string] name of this symbol", scope: "[AST_Scope/S] the current scope (not necessarily the definition scope)", @@ -784,42 +785,42 @@ var AST_Symbol = DEFNODE("Symbol", "scope name thedef", { $documentation: "Base class for all symbols", }); -var AST_SymbolAccessor = DEFNODE("SymbolAccessor", null, { +Cola.AST_SymbolAccessor = Cola.DEFNODE("SymbolAccessor", null, { $documentation: "The name of a property accessor (setter/getter function)" -}, AST_Symbol); +}, Cola.AST_Symbol); -var AST_SymbolDeclaration = DEFNODE("SymbolDeclaration", "init", { +Cola.AST_SymbolDeclaration = Cola.DEFNODE("SymbolDeclaration", "init", { $documentation: "A declaration symbol (symbol in var/const, function name or argument, symbol in catch)", $propdoc: { init: "[AST_Node*/S] array of initializers for this declaration." } -}, AST_Symbol); +}, Cola.AST_Symbol); -var AST_SymbolVar = DEFNODE("SymbolVar", null, { +Cola.AST_SymbolVar = Cola.DEFNODE("SymbolVar", null, { $documentation: "Symbol defining a variable", -}, AST_SymbolDeclaration); +}, Cola.AST_SymbolDeclaration); -var AST_SymbolConst = DEFNODE("SymbolConst", null, { +Cola.AST_SymbolConst = Cola.DEFNODE("SymbolConst", null, { $documentation: "A constant declaration" -}, AST_SymbolDeclaration); +}, Cola.AST_SymbolDeclaration); -var AST_SymbolFunarg = DEFNODE("SymbolFunarg", null, { +Cola.AST_SymbolFunarg = Cola.DEFNODE("SymbolFunarg", null, { $documentation: "Symbol naming a function argument", -}, AST_SymbolVar); +}, Cola.AST_SymbolVar); -var AST_SymbolDefun = DEFNODE("SymbolDefun", null, { +Cola.AST_SymbolDefun = Cola.DEFNODE("SymbolDefun", null, { $documentation: "Symbol defining a function", -}, AST_SymbolDeclaration); +}, Cola.AST_SymbolDeclaration); -var AST_SymbolLambda = DEFNODE("SymbolLambda", null, { +Cola.AST_SymbolLambda = Cola.DEFNODE("SymbolLambda", null, { $documentation: "Symbol naming a function expression", -}, AST_SymbolDeclaration); +}, Cola.AST_SymbolDeclaration); -var AST_SymbolCatch = DEFNODE("SymbolCatch", null, { +Cola.AST_SymbolCatch = Cola.DEFNODE("SymbolCatch", null, { $documentation: "Symbol naming the exception in catch", -}, AST_SymbolDeclaration); +}, Cola.AST_SymbolDeclaration); -var AST_Label = DEFNODE("Label", "references", { +Cola.AST_Label = Cola.DEFNODE("Label", "references", { $documentation: "Symbol naming a label (declaration)", $propdoc: { references: "[AST_LoopControl*] a list of nodes referring to this label" @@ -828,110 +829,110 @@ var AST_Label = DEFNODE("Label", "references", { this.references = []; this.thedef = this; } -}, AST_Symbol); +}, Cola.AST_Symbol); -var AST_SymbolRef = DEFNODE("SymbolRef", null, { +Cola.AST_SymbolRef = Cola.DEFNODE("SymbolRef", null, { $documentation: "Reference to some symbol (not definition/declaration)", -}, AST_Symbol); +}, Cola.AST_Symbol); -var AST_LabelRef = DEFNODE("LabelRef", null, { +Cola.AST_LabelRef = Cola.DEFNODE("LabelRef", null, { $documentation: "Reference to a label symbol", -}, AST_Symbol); +}, Cola.AST_Symbol); -var AST_This = DEFNODE("This", null, { +Cola.AST_This = Cola.DEFNODE("This", null, { $documentation: "The `this` symbol", -}, AST_Symbol); +}, Cola.AST_Symbol); -var AST_Constant = DEFNODE("Constant", null, { +Cola.AST_Constant = Cola.DEFNODE("Constant", null, { $documentation: "Base class for all constants", getValue: function() { return this.value; } }); -var AST_String = DEFNODE("String", "value", { +Cola.AST_String = Cola.DEFNODE("String", "value", { $documentation: "A string literal", $propdoc: { value: "[string] the contents of this string" } -}, AST_Constant); +}, Cola.AST_Constant); -var AST_StringTemplate = DEFNODE("StringTemplate", null, { +Cola.AST_StringTemplate = Cola.DEFNODE("StringTemplate", null, { $documentation: "A string template", $propdoc: { body: "[AST_Statement*] the contents of this string template" } -}, AST_Block); +}, Cola.AST_Block); -var AST_Number = DEFNODE("Number", "value", { +Cola.AST_Number = Cola.DEFNODE("Number", "value", { $documentation: "A number literal", $propdoc: { value: "[number] the numeric value" } -}, AST_Constant); +}, Cola.AST_Constant); -var AST_RegExp = DEFNODE("RegExp", "value", { +Cola.AST_RegExp = Cola.DEFNODE("RegExp", "value", { $documentation: "A regexp literal", $propdoc: { value: "[RegExp] the actual regexp" } -}, AST_Constant); +}, Cola.AST_Constant); -var AST_Atom = DEFNODE("Atom", null, { +Cola.AST_Atom = Cola.DEFNODE("Atom", null, { $documentation: "Base class for atoms", -}, AST_Constant); +}, Cola.AST_Constant); -var AST_Null = DEFNODE("Null", null, { +Cola.AST_Null = Cola.DEFNODE("Null", null, { $documentation: "The `null` atom", value: null -}, AST_Atom); +}, Cola.AST_Atom); -var AST_NaN = DEFNODE("NaN", null, { +Cola.AST_NaN = Cola.DEFNODE("NaN", null, { $documentation: "The impossible value", value: 0/0 -}, AST_Atom); +}, Cola.AST_Atom); -var AST_Undefined = DEFNODE("Undefined", null, { +Cola.AST_Undefined = Cola.DEFNODE("Undefined", null, { $documentation: "The `undefined` value", value: (function(){}()) -}, AST_Atom); +}, Cola.AST_Atom); -var AST_Hole = DEFNODE("Hole", null, { +Cola.AST_Hole = Cola.DEFNODE("Hole", null, { $documentation: "A hole in an array", value: (function(){}()) -}, AST_Atom); +}, Cola.AST_Atom); -var AST_Infinity = DEFNODE("Infinity", null, { +Cola.AST_Infinity = Cola.DEFNODE("Infinity", null, { $documentation: "The `Infinity` value", value: 1/0 -}, AST_Atom); +}, Cola.AST_Atom); -var AST_Boolean = DEFNODE("Boolean", null, { +Cola.AST_Boolean = Cola.DEFNODE("Boolean", null, { $documentation: "Base class for booleans", -}, AST_Atom); +}, Cola.AST_Atom); -var AST_False = DEFNODE("False", null, { +Cola.AST_False = Cola.DEFNODE("False", null, { $documentation: "The `false` atom", value: false -}, AST_Boolean); +}, Cola.AST_Boolean); -var AST_True = DEFNODE("True", null, { +Cola.AST_True = Cola.DEFNODE("True", null, { $documentation: "The `true` atom", value: true -}, AST_Boolean); +}, Cola.AST_Boolean); /* -----[ TreeWalker ]----- */ -function TreeWalker(callback) { +Cola.TreeWalker = function (callback) { this.visit = callback; this.stack = []; }; -TreeWalker.prototype = { +Cola.TreeWalker.prototype = { _visit: function(node, descend) { this.stack.push(node); var ret = this.visit(node, descend ? function(){ descend.call(node); - } : noop); + } : Cola.noop); if (!ret && descend) { descend.call(node); } @@ -958,22 +959,22 @@ TreeWalker.prototype = { } }, has_directive: function(type) { - return this.find_parent(AST_Scope).has_directive(type); + return this.find_parent(Cola.AST_Scope).has_directive(type); }, in_boolean_context: function() { var stack = this.stack; var i = stack.length, self = stack[--i]; while (i > 0) { var p = stack[--i]; - if ((p instanceof AST_If && p.condition === self) || - (p instanceof AST_Conditional && p.condition === self) || - (p instanceof AST_DWLoop && p.condition === self) || - (p instanceof AST_For && p.condition === self) || - (p instanceof AST_UnaryPrefix && p.operator == "!" && p.expression === self)) + if ((p instanceof Cola.AST_If && p.condition === self) || + (p instanceof Cola.AST_Conditional && p.condition === self) || + (p instanceof Cola.AST_DWLoop && p.condition === self) || + (p instanceof Cola.AST_For && p.condition === self) || + (p instanceof Cola.AST_UnaryPrefix && p.operator == "!" && p.expression === self)) { return true; } - if (!(p instanceof AST_Binary && (p.operator == "&&" || p.operator == "||"))) + if (!(p instanceof Cola.AST_Binary && (p.operator == "&&" || p.operator == "||"))) return false; self = p; } @@ -982,12 +983,12 @@ TreeWalker.prototype = { var stack = this.stack; if (label) for (var i = stack.length; --i >= 0;) { var x = stack[i]; - if (x instanceof AST_LabeledStatement && x.label.name == label.name) { + if (x instanceof Cola.AST_LabeledStatement && x.label.name == label.name) { return x.body; } } else for (var i = stack.length; --i >= 0;) { var x = stack[i]; - if (x instanceof AST_Switch || x instanceof AST_IterationStatement) + if (x instanceof Cola.AST_Switch || x instanceof Cola.AST_IterationStatement) return x; } } diff --git a/lib/compress.js b/lib/compress.js index b589aca5..f4b47053 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -47,7 +47,7 @@ function Compressor(options, false_by_default) { if (!(this instanceof Compressor)) return new Compressor(options, false_by_default); TreeTransformer.call(this, this.before, this.after); - this.options = defaults(options, { + this.options = Cola.defaults(options, { sequences : !false_by_default, properties : !false_by_default, dead_code : !false_by_default, @@ -80,22 +80,22 @@ function Compressor(options, false_by_default) { }; Compressor.prototype = new TreeTransformer; -merge(Compressor.prototype, { +Cola.merge(Compressor.prototype, { option: function(key) { return this.options[key] }, warn: function() { if (this.options.warnings) - AST_Node.warn.apply(AST_Node, arguments); + Cola.AST_Node.warn.apply(Cola.AST_Node, arguments); }, before: function(node, descend, in_list) { if (node._squeezed) return node; var was_scope = false; - if (node instanceof AST_Scope) { + if (node instanceof Cola.AST_Scope) { node = node.hoist_declarations(this); was_scope = true; } descend(node, this); node = node.optimize(this); - if (was_scope && node instanceof AST_Scope) { + if (was_scope && node instanceof Cola.AST_Scope) { node.drop_unused(this); descend(node, this); } @@ -117,11 +117,11 @@ merge(Compressor.prototype, { }); }; - OPT(AST_Node, function(self, compressor){ + OPT(Cola.AST_Node, function(self, compressor){ return self; }); - AST_Node.DEFMETHOD("equivalent_to", function(node){ + Cola.AST_Node.DEFMETHOD("equivalent_to", function(node){ // XXX: this is a rather expensive way to test two node's equivalence: return this.print_to_string() == node.print_to_string(); }); @@ -137,37 +137,37 @@ merge(Compressor.prototype, { function make_node_from_constant(compressor, val, orig) { // XXX: WIP. - // if (val instanceof AST_Node) return val.transform(new TreeTransformer(null, function(node){ - // if (node instanceof AST_SymbolRef) { - // var scope = compressor.find_parent(AST_Scope); + // if (val instanceof Cola.AST_Node) return val.transform(new TreeTransformer(null, function(node){ + // if (node instanceof Cola.AST_SymbolRef) { + // var scope = compressor.find_parent(Cola.AST_Scope); // var def = scope.find_variable(node); // node.thedef = def; // return node; // } // })).transform(compressor); - if (val instanceof AST_Node) return val.transform(compressor); + if (val instanceof Cola.AST_Node) return val.transform(compressor); switch (typeof val) { case "string": - return make_node(AST_String, orig, { + return make_node(Cola.AST_String, orig, { value: val }).optimize(compressor); case "number": - return make_node(isNaN(val) ? AST_NaN : AST_Number, orig, { + return make_node(isNaN(val) ? Cola.AST_NaN : Cola.AST_Number, orig, { value: val }).optimize(compressor); case "boolean": - return make_node(val ? AST_True : AST_False, orig).optimize(compressor); + return make_node(val ? Cola.AST_True : Cola.AST_False, orig).optimize(compressor); case "undefined": - return make_node(AST_Undefined, orig).optimize(compressor); + return make_node(Cola.AST_Undefined, orig).optimize(compressor); default: if (val === null) { - return make_node(AST_Null, orig).optimize(compressor); + return make_node(Cola.AST_Null, orig).optimize(compressor); } if (val instanceof RegExp) { - return make_node(AST_RegExp, orig).optimize(compressor); + return make_node(Cola.AST_RegExp, orig).optimize(compressor); } - throw new Error(string_template("Can't handle constant of type: {type}", { + throw new Error(Cola.string_template("Can't handle constant of type: {type}", { type: typeof val })); } @@ -175,23 +175,23 @@ merge(Compressor.prototype, { function as_statement_array(thing) { if (thing === null) return []; - if (thing instanceof AST_BlockStatement) return thing.body; - if (thing instanceof AST_EmptyStatement) return []; - if (thing instanceof AST_Statement) return [ thing ]; + if (thing instanceof Cola.AST_BlockStatement) return thing.body; + if (thing instanceof Cola.AST_EmptyStatement) return []; + if (thing instanceof Cola.AST_Statement) return [ thing ]; throw new Error("Can't convert thing to statement array"); }; function is_empty(thing) { if (thing === null) return true; - if (thing instanceof AST_EmptyStatement) return true; - if (thing instanceof AST_BlockStatement) return thing.body.length == 0; + if (thing instanceof Cola.AST_EmptyStatement) return true; + if (thing instanceof Cola.AST_BlockStatement) return thing.body.length == 0; return false; }; function loop_body(x) { - if (x instanceof AST_Switch) return x; - if (x instanceof AST_For || x instanceof AST_ForIn || x instanceof AST_DWLoop) { - return (x.body instanceof AST_BlockStatement ? x.body : x); + if (x instanceof Cola.AST_Switch) return x; + if (x instanceof Cola.AST_For || x instanceof Cola.AST_ForIn || x instanceof Cola.AST_DWLoop) { + return (x.body instanceof Cola.AST_BlockStatement ? x.body : x); } return x; }; @@ -226,16 +226,16 @@ merge(Compressor.prototype, { function process_for_angular(statements) { function make_injector(func, name) { - return make_node(AST_SimpleStatement, func, { - body: make_node(AST_Assign, func, { + return make_node(Cola.AST_SimpleStatement, func, { + body: make_node(Cola.AST_Assign, func, { operator: "=", - left: make_node(AST_Dot, name, { - expression: make_node(AST_SymbolRef, name, name), + left: make_node(Cola.AST_Dot, name, { + expression: make_node(Cola.AST_SymbolRef, name, name), property: "$inject" }), - right: make_node(AST_Array, func, { + right: make_node(Cola.AST_Array, func, { elements: func.argnames.map(function(sym){ - return make_node(AST_String, sym, { value: sym.name }); + return make_node(Cola.AST_String, sym, { value: sym.name }); }) }) }) @@ -249,12 +249,12 @@ merge(Compressor.prototype, { var last = comments.pop(); if (/@ngInject/.test(last.value)) { // case 1: defun - if (stat instanceof AST_Defun) { + if (stat instanceof Cola.AST_Defun) { a.push(make_injector(stat, stat.name)); } - else if (stat instanceof AST_Definitions) { + else if (stat instanceof Cola.AST_Definitions) { stat.definitions.forEach(function(def){ - if (def.value && def.value instanceof AST_Lambda) { + if (def.value && def.value instanceof Cola.AST_Lambda) { a.push(make_injector(def.value, def.name)); } }); @@ -271,12 +271,12 @@ merge(Compressor.prototype, { function eliminate_spurious_blocks(statements) { var seen_dirs = []; return statements.reduce(function(a, stat){ - if (stat instanceof AST_BlockStatement) { + if (stat instanceof Cola.AST_BlockStatement) { CHANGED = true; a.push.apply(a, eliminate_spurious_blocks(stat.body)); - } else if (stat instanceof AST_EmptyStatement) { + } else if (stat instanceof Cola.AST_EmptyStatement) { CHANGED = true; - } else if (stat instanceof AST_Directive) { + } else if (stat instanceof Cola.AST_Directive) { if (seen_dirs.indexOf(stat.value) < 0) { a.push(stat); seen_dirs.push(stat.value); @@ -292,27 +292,27 @@ merge(Compressor.prototype, { function handle_if_return(statements, compressor) { var self = compressor.self(); - var in_lambda = self instanceof AST_Lambda; + var in_lambda = self instanceof Cola.AST_Lambda; var ret = []; loop: for (var i = statements.length; --i >= 0;) { var stat = statements[i]; switch (true) { - case (in_lambda && stat instanceof AST_Return && !stat.value && ret.length == 0): + case (in_lambda && stat instanceof Cola.AST_Return && !stat.value && ret.length == 0): CHANGED = true; // note, ret.length is probably always zero // because we drop unreachable code before this // step. nevertheless, it's good to check. continue loop; - case stat instanceof AST_If: - if (stat.body instanceof AST_Return) { + case stat instanceof Cola.AST_If: + if (stat.body instanceof Cola.AST_Return) { //--- // pretty silly case, but: // if (foo()) return; return; ==> foo(); return; if (((in_lambda && ret.length == 0) - || (ret[0] instanceof AST_Return && !ret[0].value)) + || (ret[0] instanceof Cola.AST_Return && !ret[0].value)) && !stat.body.value && !stat.alternative) { CHANGED = true; - var cond = make_node(AST_SimpleStatement, stat.condition, { + var cond = make_node(Cola.AST_SimpleStatement, stat.condition, { body: stat.condition }); ret.unshift(cond); @@ -320,7 +320,7 @@ merge(Compressor.prototype, { } //--- // if (foo()) return x; return y; ==> return foo() ? x : y; - if (ret[0] instanceof AST_Return && stat.body.value && ret[0].value && !stat.alternative) { + if (ret[0] instanceof Cola.AST_Return && stat.body.value && ret[0].value && !stat.alternative) { CHANGED = true; stat = stat.clone(); stat.alternative = ret[0]; @@ -329,11 +329,11 @@ merge(Compressor.prototype, { } //--- // if (foo()) return x; [ return ; ] ==> return foo() ? x : undefined; - if ((ret.length == 0 || ret[0] instanceof AST_Return) && stat.body.value && !stat.alternative && in_lambda) { + if ((ret.length == 0 || ret[0] instanceof Cola.AST_Return) && stat.body.value && !stat.alternative && in_lambda) { CHANGED = true; stat = stat.clone(); - stat.alternative = ret[0] || make_node(AST_Return, stat, { - value: make_node(AST_Undefined, stat) + stat.alternative = ret[0] || make_node(Cola.AST_Return, stat, { + value: make_node(Cola.AST_Undefined, stat) }); ret[0] = stat.transform(compressor); continue loop; @@ -344,7 +344,7 @@ merge(Compressor.prototype, { CHANGED = true; stat = stat.clone(); stat.condition = stat.condition.negate(compressor); - stat.body = make_node(AST_BlockStatement, stat, { + stat.body = make_node(Cola.AST_BlockStatement, stat, { body: as_statement_array(stat.alternative).concat(ret) }); stat.alternative = null; @@ -352,11 +352,11 @@ merge(Compressor.prototype, { continue loop; } //--- - if (ret.length == 1 && in_lambda && ret[0] instanceof AST_SimpleStatement - && (!stat.alternative || stat.alternative instanceof AST_SimpleStatement)) { + if (ret.length == 1 && in_lambda && ret[0] instanceof Cola.AST_SimpleStatement + && (!stat.alternative || stat.alternative instanceof Cola.AST_SimpleStatement)) { CHANGED = true; - ret.push(make_node(AST_Return, ret[0], { - value: make_node(AST_Undefined, ret[0]) + ret.push(make_node(Cola.AST_Return, ret[0], { + value: make_node(Cola.AST_Undefined, ret[0]) }).transform(compressor)); ret = as_statement_array(stat.alternative).concat(ret); ret.unshift(stat); @@ -365,21 +365,21 @@ merge(Compressor.prototype, { } var ab = aborts(stat.body); - var lct = ab instanceof AST_LoopControl ? compressor.loopcontrol_target(ab.label) : null; - if (ab && ((ab instanceof AST_Return && !ab.value && in_lambda) - || (ab instanceof AST_Continue && self === loop_body(lct)) - || (ab instanceof AST_Break && lct instanceof AST_BlockStatement && self === lct))) { + var lct = ab instanceof Cola.AST_LoopControl ? compressor.loopcontrol_target(ab.label) : null; + if (ab && ((ab instanceof Cola.AST_Return && !ab.value && in_lambda) + || (ab instanceof Cola.AST_Continue && self === loop_body(lct)) + || (ab instanceof Cola.AST_Break && lct instanceof Cola.AST_BlockStatement && self === lct))) { if (ab.label) { - remove(ab.label.thedef.references, ab); + Cola.remove(ab.label.thedef.references, ab); } CHANGED = true; var body = as_statement_array(stat.body).slice(0, -1); stat = stat.clone(); stat.condition = stat.condition.negate(compressor); - stat.body = make_node(AST_BlockStatement, stat, { + stat.body = make_node(Cola.AST_BlockStatement, stat, { body: as_statement_array(stat.alternative).concat(ret) }); - stat.alternative = make_node(AST_BlockStatement, stat, { + stat.alternative = make_node(Cola.AST_BlockStatement, stat, { body: body }); ret = [ stat.transform(compressor) ]; @@ -387,19 +387,19 @@ merge(Compressor.prototype, { } var ab = aborts(stat.alternative); - var lct = ab instanceof AST_LoopControl ? compressor.loopcontrol_target(ab.label) : null; - if (ab && ((ab instanceof AST_Return && !ab.value && in_lambda) - || (ab instanceof AST_Continue && self === loop_body(lct)) - || (ab instanceof AST_Break && lct instanceof AST_BlockStatement && self === lct))) { + var lct = ab instanceof Cola.AST_LoopControl ? compressor.loopcontrol_target(ab.label) : null; + if (ab && ((ab instanceof Cola.AST_Return && !ab.value && in_lambda) + || (ab instanceof Cola.AST_Continue && self === loop_body(lct)) + || (ab instanceof Cola.AST_Break && lct instanceof Cola.AST_BlockStatement && self === lct))) { if (ab.label) { - remove(ab.label.thedef.references, ab); + Cola.remove(ab.label.thedef.references, ab); } CHANGED = true; stat = stat.clone(); - stat.body = make_node(AST_BlockStatement, stat.body, { + stat.body = make_node(Cola.AST_BlockStatement, stat.body, { body: as_statement_array(stat.body).concat(ret) }); - stat.alternative = make_node(AST_BlockStatement, stat.alternative, { + stat.alternative = make_node(Cola.AST_BlockStatement, stat.alternative, { body: as_statement_array(stat.alternative).slice(0, -1) }); ret = [ stat.transform(compressor) ]; @@ -424,14 +424,14 @@ merge(Compressor.prototype, { if (has_quit) { extract_declarations_from_unreachable_code(compressor, stat, a); } else { - if (stat instanceof AST_LoopControl) { + if (stat instanceof Cola.AST_LoopControl) { var lct = compressor.loopcontrol_target(stat.label); - if ((stat instanceof AST_Break - && lct instanceof AST_BlockStatement - && loop_body(lct) === self) || (stat instanceof AST_Continue + if ((stat instanceof Cola.AST_Break + && lct instanceof Cola.AST_BlockStatement + && loop_body(lct) === self) || (stat instanceof Cola.AST_Continue && loop_body(lct) === self)) { if (stat.label) { - remove(stat.label.thedef.references, stat); + Cola.remove(stat.label.thedef.references, stat); } } else { a.push(stat); @@ -451,14 +451,14 @@ merge(Compressor.prototype, { if (statements.length < 2) return statements; var seq = [], ret = []; function push_seq() { - seq = AST_Seq.from_array(seq); - if (seq) ret.push(make_node(AST_SimpleStatement, seq, { + seq = Cola.AST_Seq.from_array(seq); + if (seq) ret.push(make_node(Cola.AST_SimpleStatement, seq, { body: seq })); seq = []; }; statements.forEach(function(stat){ - if (stat instanceof AST_SimpleStatement) seq.push(stat.body); + if (stat instanceof Cola.AST_SimpleStatement) seq.push(stat.body); else push_seq(), ret.push(stat); }); push_seq(); @@ -471,24 +471,24 @@ merge(Compressor.prototype, { function cons_seq(right) { ret.pop(); var left = prev.body; - if (left instanceof AST_Seq) { + if (left instanceof Cola.AST_Seq) { left.add(right); } else { - left = AST_Seq.cons(left, right); + left = Cola.AST_Seq.cons(left, right); } return left.transform(compressor); }; var ret = [], prev = null; statements.forEach(function(stat){ if (prev) { - if (stat instanceof AST_For) { + if (stat instanceof Cola.AST_For) { var opera = {}; try { - prev.body.walk(new TreeWalker(function(node){ - if (node instanceof AST_Binary && node.operator == "in") + prev.body.walk(new Cola.TreeWalker(function(node){ + if (node instanceof Cola.AST_Binary && node.operator == "in") throw opera; })); - if (stat.init && !(stat.init instanceof AST_Definitions)) { + if (stat.init && !(stat.init instanceof Cola.AST_Definitions)) { stat.init = cons_seq(stat.init); } else if (!stat.init) { @@ -499,24 +499,24 @@ merge(Compressor.prototype, { if (ex !== opera) throw ex; } } - else if (stat instanceof AST_If) { + else if (stat instanceof Cola.AST_If) { stat.condition = cons_seq(stat.condition); } - else if (stat instanceof AST_With) { + else if (stat instanceof Cola.AST_With) { stat.expression = cons_seq(stat.expression); } - else if (stat instanceof AST_Exit && stat.value) { + else if (stat instanceof Cola.AST_Exit && stat.value) { stat.value = cons_seq(stat.value); } - else if (stat instanceof AST_Exit) { - stat.value = cons_seq(make_node(AST_Undefined, stat)); + else if (stat instanceof Cola.AST_Exit) { + stat.value = cons_seq(make_node(Cola.AST_Undefined, stat)); } - else if (stat instanceof AST_Switch) { + else if (stat instanceof Cola.AST_Switch) { stat.expression = cons_seq(stat.expression); } } ret.push(stat); - prev = stat instanceof AST_SimpleStatement ? stat : null; + prev = stat instanceof Cola.AST_SimpleStatement ? stat : null; }); return ret; }; @@ -524,12 +524,12 @@ merge(Compressor.prototype, { function join_consecutive_vars(statements, compressor) { var prev = null; return statements.reduce(function(a, stat){ - if (stat instanceof AST_Definitions && prev && prev.TYPE == stat.TYPE) { + if (stat instanceof Cola.AST_Definitions && prev && prev.TYPE == stat.TYPE) { prev.definitions = prev.definitions.concat(stat.definitions); CHANGED = true; } - else if (stat instanceof AST_For - && prev instanceof AST_Definitions + else if (stat instanceof Cola.AST_For + && prev instanceof Cola.AST_Definitions && (!stat.init || stat.init.TYPE == prev.TYPE)) { CHANGED = true; a.pop(); @@ -551,22 +551,22 @@ merge(Compressor.prototype, { function negate_iifes(statements, compressor) { statements.forEach(function(stat){ - if (stat instanceof AST_SimpleStatement) { + if (stat instanceof Cola.AST_SimpleStatement) { stat.body = (function transform(thing) { return thing.transform(new TreeTransformer(function(node){ - if (node instanceof AST_Call && node.expression instanceof AST_Function) { - return make_node(AST_UnaryPrefix, node, { + if (node instanceof Cola.AST_Call && node.expression instanceof Cola.AST_Function) { + return make_node(Cola.AST_UnaryPrefix, node, { operator: "!", expression: node }); } - else if (node instanceof AST_Call) { + else if (node instanceof Cola.AST_Call) { node.expression = transform(node.expression); } - else if (node instanceof AST_Seq) { + else if (node instanceof Cola.AST_Seq) { node.car = transform(node.car); } - else if (node instanceof AST_Conditional) { + else if (node instanceof Cola.AST_Conditional) { var expr = transform(node.condition); if (expr !== node.condition) { // it has been negated, reverse @@ -587,18 +587,18 @@ merge(Compressor.prototype, { function extract_declarations_from_unreachable_code(compressor, stat, target) { compressor.warn("Dropping unreachable code [{file}:{line},{col}]", stat.start); - stat.walk(new TreeWalker(function(node){ - if (node instanceof AST_Definitions) { + stat.walk(new Cola.TreeWalker(function(node){ + if (node instanceof Cola.AST_Definitions) { compressor.warn("Declarations in unreachable code! [{file}:{line},{col}]", node.start); node.remove_initializers(); target.push(node); return true; } - if (node instanceof AST_Defun) { + if (node instanceof Cola.AST_Defun) { target.push(node); return true; } - if (node instanceof AST_Scope) { + if (node instanceof Cola.AST_Scope) { return true; } })); @@ -610,53 +610,53 @@ merge(Compressor.prototype, { (function (def){ var unary_bool = [ "!", "delete" ]; var binary_bool = [ "in", "instanceof", "==", "!=", "===", "!==", "<", "<=", ">=", ">" ]; - def(AST_Node, function(){ return false }); - def(AST_UnaryPrefix, function(){ - return member(this.operator, unary_bool); + def(Cola.AST_Node, function(){ return false }); + def(Cola.AST_UnaryPrefix, function(){ + return Cola.member(this.operator, unary_bool); }); - def(AST_Binary, function(){ - return member(this.operator, binary_bool) || + def(Cola.AST_Binary, function(){ + return Cola.member(this.operator, binary_bool) || ( (this.operator == "&&" || this.operator == "||") && this.left.is_boolean() && this.right.is_boolean() ); }); - def(AST_Conditional, function(){ + def(Cola.AST_Conditional, function(){ return this.consequent.is_boolean() && this.alternative.is_boolean(); }); - def(AST_Assign, function(){ + def(Cola.AST_Assign, function(){ return this.operator == "=" && this.right.is_boolean(); }); - def(AST_Seq, function(){ + def(Cola.AST_Seq, function(){ return this.cdr.is_boolean(); }); - def(AST_True, function(){ return true }); - def(AST_False, function(){ return true }); + def(Cola.AST_True, function(){ return true }); + def(Cola.AST_False, function(){ return true }); })(function(node, func){ node.DEFMETHOD("is_boolean", func); }); // methods to determine if an expression has a string result type (function (def){ - def(AST_Node, function(){ return false }); - def(AST_String, function(){ return true }); - def(AST_UnaryPrefix, function(){ + def(Cola.AST_Node, function(){ return false }); + def(Cola.AST_String, function(){ return true }); + def(Cola.AST_UnaryPrefix, function(){ return this.operator == "typeof"; }); - def(AST_Binary, function(compressor){ + def(Cola.AST_Binary, function(compressor){ return this.operator == "+" && (this.left.is_string(compressor) || this.right.is_string(compressor)); }); - def(AST_Assign, function(compressor){ + def(Cola.AST_Assign, function(compressor){ return (this.operator == "=" || this.operator == "+=") && this.right.is_string(compressor); }); - def(AST_Seq, function(compressor){ + def(Cola.AST_Seq, function(compressor){ return this.cdr.is_string(compressor); }); - def(AST_Conditional, function(compressor){ + def(Cola.AST_Conditional, function(compressor){ return this.consequent.is_string(compressor) && this.alternative.is_string(compressor); }); - def(AST_Call, function(compressor){ + def(Cola.AST_Call, function(compressor){ return compressor.option("unsafe") - && this.expression instanceof AST_SymbolRef + && this.expression instanceof Cola.AST_SymbolRef && this.expression.name == "String" && this.expression.undeclared(); }); @@ -676,10 +676,10 @@ merge(Compressor.prototype, { // elements. If the node has been successfully reduced to a // constant, then the second element tells us the value; // otherwise the second element is missing. The first element - // of the array is always an AST_Node descendant; if + // of the array is always an Cola.AST_Node descendant; if // evaluation was successful it's a node that represents the // constant; otherwise it's the original or a replacement node. - AST_Node.DEFMETHOD("evaluate", function(compressor){ + Cola.AST_Node.DEFMETHOD("evaluate", function(compressor){ if (!compressor.option("evaluate")) return [ this ]; try { var val = this._eval(compressor); @@ -689,12 +689,12 @@ merge(Compressor.prototype, { return [ this ]; } }); - def(AST_Statement, function(){ - throw new Error(string_template("Cannot evaluate a statement [{file}:{line},{col}]", this.start)); + def(Cola.AST_Statement, function(){ + throw new Error(Cola.string_template("Cannot evaluate a statement [{file}:{line},{col}]", this.start)); }); - def(AST_Function, function(){ - // XXX: AST_Function inherits from AST_Scope, which itself - // inherits from AST_Statement; however, an AST_Function + def(Cola.AST_Function, function(){ + // XXX: Cola.AST_Function inherits from Cola.AST_Scope, which itself + // inherits from Cola.AST_Statement; however, an Cola.AST_Function // isn't really a statement. This could byte in other // places too. :-( Wish JS had multiple inheritance. throw def; @@ -704,20 +704,20 @@ merge(Compressor.prototype, { return node._eval(compressor); }; - def(AST_Node, function(){ + def(Cola.AST_Node, function(){ throw def; // not constant }); - def(AST_Constant, function(){ + def(Cola.AST_Constant, function(){ return this.getValue(); }); - def(AST_UnaryPrefix, function(compressor){ + def(Cola.AST_UnaryPrefix, function(compressor){ var e = this.expression; switch (this.operator) { case "!": return !ev(e, compressor); case "typeof": // Function would be evaluated to an array and so typeof would // incorrectly return 'object'. Hence making is a special case. - if (e instanceof AST_Function) return typeof function(){}; + if (e instanceof Cola.AST_Function) return typeof function(){}; e = ev(e, compressor); @@ -736,7 +736,7 @@ merge(Compressor.prototype, { } throw def; }); - def(AST_Binary, function(c){ + def(Cola.AST_Binary, function(c){ var left = this.left, right = this.right; switch (this.operator) { case "&&" : return ev(left, c) && ev(right, c); @@ -765,12 +765,12 @@ merge(Compressor.prototype, { } throw def; }); - def(AST_Conditional, function(compressor){ + def(Cola.AST_Conditional, function(compressor){ return ev(this.condition, compressor) ? ev(this.consequent, compressor) : ev(this.alternative, compressor); }); - def(AST_SymbolRef, function(compressor){ + def(Cola.AST_SymbolRef, function(compressor){ var d = this.definition(); if (d && d.constant && d.init) return ev(d.init, compressor); throw def; @@ -782,37 +782,37 @@ merge(Compressor.prototype, { // method to negate an expression (function(def){ function basic_negation(exp) { - return make_node(AST_UnaryPrefix, exp, { + return make_node(Cola.AST_UnaryPrefix, exp, { operator: "!", expression: exp }); }; - def(AST_Node, function(){ + def(Cola.AST_Node, function(){ return basic_negation(this); }); - def(AST_Statement, function(){ + def(Cola.AST_Statement, function(){ throw new Error("Cannot negate a statement"); }); - def(AST_Function, function(){ + def(Cola.AST_Function, function(){ return basic_negation(this); }); - def(AST_UnaryPrefix, function(){ + def(Cola.AST_UnaryPrefix, function(){ if (this.operator == "!") return this.expression; return basic_negation(this); }); - def(AST_Seq, function(compressor){ + def(Cola.AST_Seq, function(compressor){ var self = this.clone(); self.cdr = self.cdr.negate(compressor); return self; }); - def(AST_Conditional, function(compressor){ + def(Cola.AST_Conditional, function(compressor){ var self = this.clone(); self.consequent = self.consequent.negate(compressor); self.alternative = self.alternative.negate(compressor); return best_of(basic_negation(this), self); }); - def(AST_Binary, function(compressor){ + def(Cola.AST_Binary, function(compressor){ var self = this.clone(), op = this.operator; if (compressor.option("unsafe_comps")) { switch (op) { @@ -848,19 +848,19 @@ merge(Compressor.prototype, { // determine if expression has side effects (function(def){ - def(AST_Node, function(compressor){ return true }); + def(Cola.AST_Node, function(compressor){ return true }); - def(AST_EmptyStatement, function(compressor){ return false }); - def(AST_Constant, function(compressor){ return false }); - def(AST_This, function(compressor){ return false }); + def(Cola.AST_EmptyStatement, function(compressor){ return false }); + def(Cola.AST_Constant, function(compressor){ return false }); + def(Cola.AST_This, function(compressor){ return false }); - def(AST_Call, function(compressor){ + def(Cola.AST_Call, function(compressor){ var pure = compressor.option("pure_funcs"); if (!pure) return true; return pure.indexOf(this.expression.print_to_string()) < 0; }); - def(AST_Block, function(compressor){ + def(Cola.AST_Block, function(compressor){ for (var i = this.body.length; --i >= 0;) { if (this.body[i].has_side_effects(compressor)) return true; @@ -868,56 +868,56 @@ merge(Compressor.prototype, { return false; }); - def(AST_SimpleStatement, function(compressor){ + def(Cola.AST_SimpleStatement, function(compressor){ return this.body.has_side_effects(compressor); }); - def(AST_Defun, function(compressor){ return true }); - def(AST_Function, function(compressor){ return false }); - def(AST_Binary, function(compressor){ + def(Cola.AST_Defun, function(compressor){ return true }); + def(Cola.AST_Function, function(compressor){ return false }); + def(Cola.AST_Binary, function(compressor){ return this.left.has_side_effects(compressor) || this.right.has_side_effects(compressor); }); - def(AST_Assign, function(compressor){ return true }); - def(AST_Conditional, function(compressor){ + def(Cola.AST_Assign, function(compressor){ return true }); + def(Cola.AST_Conditional, function(compressor){ return this.condition.has_side_effects(compressor) || this.consequent.has_side_effects(compressor) || this.alternative.has_side_effects(compressor); }); - def(AST_Unary, function(compressor){ + def(Cola.AST_Unary, function(compressor){ return this.operator == "delete" || this.operator == "++" || this.operator == "--" || this.expression.has_side_effects(compressor); }); - def(AST_SymbolRef, function(compressor){ return false }); - def(AST_Object, function(compressor){ + def(Cola.AST_SymbolRef, function(compressor){ return false }); + def(Cola.AST_Object, function(compressor){ for (var i = this.properties.length; --i >= 0;) if (this.properties[i].has_side_effects(compressor)) return true; return false; }); - def(AST_ObjectProperty, function(compressor){ + def(Cola.AST_ObjectProperty, function(compressor){ return this.value.has_side_effects(compressor); }); - def(AST_Array, function(compressor){ + def(Cola.AST_Array, function(compressor){ for (var i = this.elements.length; --i >= 0;) if (this.elements[i].has_side_effects(compressor)) return true; return false; }); - def(AST_Dot, function(compressor){ + def(Cola.AST_Dot, function(compressor){ if (!compressor.option("pure_getters")) return true; return this.expression.has_side_effects(compressor); }); - def(AST_Sub, function(compressor){ + def(Cola.AST_Sub, function(compressor){ if (!compressor.option("pure_getters")) return true; return this.expression.has_side_effects(compressor) || this.property.has_side_effects(compressor); }); - def(AST_PropAccess, function(compressor){ + def(Cola.AST_PropAccess, function(compressor){ return !compressor.option("pure_getters"); }); - def(AST_Seq, function(compressor){ + def(Cola.AST_Seq, function(compressor){ return this.car.has_side_effects(compressor) || this.cdr.has_side_effects(compressor); }); @@ -930,15 +930,15 @@ merge(Compressor.prototype, { return thing && thing.aborts(); }; (function(def){ - def(AST_Statement, function(){ return null }); - def(AST_Jump, function(){ return this }); + def(Cola.AST_Statement, function(){ return null }); + def(Cola.AST_Jump, function(){ return this }); function block_aborts(){ var n = this.body.length; return n > 0 && aborts(this.body[n - 1]); }; - def(AST_BlockStatement, block_aborts); - def(AST_SwitchBranch, block_aborts); - def(AST_If, function(){ + def(Cola.AST_BlockStatement, block_aborts); + def(Cola.AST_SwitchBranch, block_aborts); + def(Cola.AST_If, function(){ return this.alternative && aborts(this.body) && aborts(this.alternative); }); })(function(node, func){ @@ -947,59 +947,59 @@ merge(Compressor.prototype, { /* -----[ optimizers ]----- */ - OPT(AST_Directive, function(self, compressor){ + OPT(Cola.AST_Directive, function(self, compressor){ if (self.scope.has_directive(self.value) !== self.scope) { - return make_node(AST_EmptyStatement, self); + return make_node(Cola.AST_EmptyStatement, self); } return self; }); - OPT(AST_Debugger, function(self, compressor){ + OPT(Cola.AST_Debugger, function(self, compressor){ if (compressor.option("drop_debugger")) - return make_node(AST_EmptyStatement, self); + return make_node(Cola.AST_EmptyStatement, self); return self; }); - OPT(AST_LabeledStatement, function(self, compressor){ - if (self.body instanceof AST_Break + OPT(Cola.AST_LabeledStatement, function(self, compressor){ + if (self.body instanceof Cola.AST_Break && compressor.loopcontrol_target(self.body.label) === self.body) { - return make_node(AST_EmptyStatement, self); + return make_node(Cola.AST_EmptyStatement, self); } return self.label.references.length == 0 ? self.body : self; }); - OPT(AST_Block, function(self, compressor){ + OPT(Cola.AST_Block, function(self, compressor){ self.body = tighten_body(self.body, compressor); return self; }); - OPT(AST_BlockStatement, function(self, compressor){ + OPT(Cola.AST_BlockStatement, function(self, compressor){ self.body = tighten_body(self.body, compressor); switch (self.body.length) { case 1: return self.body[0]; - case 0: return make_node(AST_EmptyStatement, self); + case 0: return make_node(Cola.AST_EmptyStatement, self); } return self; }); - AST_Scope.DEFMETHOD("drop_unused", function(compressor){ + Cola.AST_Scope.DEFMETHOD("drop_unused", function(compressor){ var self = this; if (compressor.option("unused") - && !(self instanceof AST_Toplevel) + && !(self instanceof Cola.AST_Toplevel) && !self.uses_eval ) { var in_use = []; - var initializations = new Dictionary(); + var initializations = new Cola.Dictionary(); // pass 1: find out which symbols are directly used in // this scope (not in nested scopes). var scope = this; - var tw = new TreeWalker(function(node, descend){ + var tw = new Cola.TreeWalker(function(node, descend){ if (node !== self) { - if (node instanceof AST_Defun) { + if (node instanceof Cola.AST_Defun) { initializations.add(node.name.name, node); return true; // don't go in nested scopes } - if (node instanceof AST_Definitions && scope === self) { + if (node instanceof Cola.AST_Definitions && scope === self) { node.definitions.forEach(function(def){ if (def.value) { initializations.add(def.name.name, def.value); @@ -1010,11 +1010,11 @@ merge(Compressor.prototype, { }); return true; } - if (node instanceof AST_SymbolRef) { - push_uniq(in_use, node.definition()); + if (node instanceof Cola.AST_SymbolRef) { + Cola.push_uniq(in_use, node.definition()); return true; } - if (node instanceof AST_Scope) { + if (node instanceof Cola.AST_Scope) { var save_scope = scope; scope = node; descend(); @@ -1029,12 +1029,12 @@ merge(Compressor.prototype, { // symbols (that may not be in_use). for (var i = 0; i < in_use.length; ++i) { in_use[i].orig.forEach(function(decl){ - // undeclared globals will be instanceof AST_SymbolRef + // undeclared globals will be instanceof Cola.AST_SymbolRef var init = initializations.get(decl.name); if (init) init.forEach(function(init){ - var tw = new TreeWalker(function(node){ - if (node instanceof AST_SymbolRef) { - push_uniq(in_use, node.definition()); + var tw = new Cola.TreeWalker(function(node){ + if (node instanceof Cola.AST_SymbolRef) { + Cola.push_uniq(in_use, node.definition()); } }); init.walk(tw); @@ -1044,7 +1044,7 @@ merge(Compressor.prototype, { // pass 3: we should drop declarations not in_use var tt = new TreeTransformer( function before(node, descend, in_list) { - if (node instanceof AST_Lambda && !(node instanceof AST_Accessor)) { + if (node instanceof Cola.AST_Lambda && !(node instanceof Cola.AST_Accessor)) { if (!compressor.option("keep_fargs")) { for (var a = node.argnames, i = a.length; --i >= 0;) { var sym = a[i]; @@ -1061,21 +1061,21 @@ merge(Compressor.prototype, { } } } - if (node instanceof AST_Defun && node !== self) { - if (!member(node.name.definition(), in_use)) { + if (node instanceof Cola.AST_Defun && node !== self) { + if (!Cola.member(node.name.definition(), in_use)) { compressor.warn("Dropping unused function {name} [{file}:{line},{col}]", { name : node.name.name, file : node.name.start.file, line : node.name.start.line, col : node.name.start.col }); - return make_node(AST_EmptyStatement, node); + return make_node(Cola.AST_EmptyStatement, node); } return node; } - if (node instanceof AST_Definitions && !(tt.parent() instanceof AST_ForIn)) { + if (node instanceof Cola.AST_Definitions && !(tt.parent() instanceof Cola.AST_ForIn)) { var def = node.definitions.filter(function(def){ - if (member(def.name.definition(), in_use)) return true; + if (Cola.member(def.name.definition(), in_use)) return true; var w = { name : def.name.name, file : def.name.start.file, @@ -1091,7 +1091,7 @@ merge(Compressor.prototype, { return false; }); // place uninitialized names at the start - def = mergeSort(def, function(a, b){ + def = Cola.mergeSort(def, function(a, b){ if (!a.value && b.value) return -1; if (!b.value && a.value) return 1; return 0; @@ -1108,23 +1108,23 @@ merge(Compressor.prototype, { } else { if (side_effects.length > 0) { side_effects.push(x.value); - x.value = AST_Seq.from_array(side_effects); + x.value = Cola.AST_Seq.from_array(side_effects); side_effects = []; } ++i; } } if (side_effects.length > 0) { - side_effects = make_node(AST_BlockStatement, node, { - body: [ make_node(AST_SimpleStatement, node, { - body: AST_Seq.from_array(side_effects) + side_effects = make_node(Cola.AST_BlockStatement, node, { + body: [ make_node(Cola.AST_SimpleStatement, node, { + body: Cola.AST_Seq.from_array(side_effects) }) ] }); } else { side_effects = null; } if (def.length == 0 && !side_effects) { - return make_node(AST_EmptyStatement, node); + return make_node(Cola.AST_EmptyStatement, node); } if (def.length == 0) { return side_effects; @@ -1136,10 +1136,10 @@ merge(Compressor.prototype, { } return node; } - if (node instanceof AST_For) { + if (node instanceof Cola.AST_For) { descend(node, this); - if (node.init instanceof AST_BlockStatement) { + if (node.init instanceof Cola.AST_BlockStatement) { // certain combination of unused name + side effect leads to: // https://github.com/mishoo/UglifyJS2/issues/44 // that's an invalid AST. @@ -1149,12 +1149,12 @@ merge(Compressor.prototype, { node.init = node.init.body.slice(-1)[0].body; body.push(node); - return in_list ? MAP.splice(body) : make_node(AST_BlockStatement, node, { + return in_list ? Cola.MAP.splice(body) : make_node(Cola.AST_BlockStatement, node, { body: body }); } } - if (node instanceof AST_Scope && node !== self) + if (node instanceof Cola.AST_Scope && node !== self) return node; } ); @@ -1162,20 +1162,20 @@ merge(Compressor.prototype, { } }); - AST_Scope.DEFMETHOD("hoist_declarations", function(compressor){ + Cola.AST_Scope.DEFMETHOD("hoist_declarations", function(compressor){ var hoist_funs = compressor.option("hoist_funs"); var hoist_vars = compressor.option("hoist_vars"); var self = this; if (hoist_funs || hoist_vars) { var dirs = []; var hoisted = []; - var vars = new Dictionary(), vars_found = 0, var_decl = 0; + var vars = new Cola.Dictionary(), vars_found = 0, var_decl = 0; // let's count var_decl first, we seem to waste a lot of // space if we hoist `var` when there's only one. - self.walk(new TreeWalker(function(node){ - if (node instanceof AST_Scope && node !== self) + self.walk(new Cola.TreeWalker(function(node){ + if (node instanceof Cola.AST_Scope && node !== self) return true; - if (node instanceof AST_Var) { + if (node instanceof Cola.AST_Var) { ++var_decl; return true; } @@ -1184,34 +1184,34 @@ merge(Compressor.prototype, { var tt = new TreeTransformer( function before(node) { if (node !== self) { - if (node instanceof AST_Directive) { + if (node instanceof Cola.AST_Directive) { dirs.push(node); - return make_node(AST_EmptyStatement, node); + return make_node(Cola.AST_EmptyStatement, node); } - if (node instanceof AST_Defun && hoist_funs) { + if (node instanceof Cola.AST_Defun && hoist_funs) { hoisted.push(node); - return make_node(AST_EmptyStatement, node); + return make_node(Cola.AST_EmptyStatement, node); } - if (node instanceof AST_Var && hoist_vars) { + if (node instanceof Cola.AST_Var && hoist_vars) { node.definitions.forEach(function(def){ vars.set(def.name.name, def); ++vars_found; }); var seq = node.to_assignments(); var p = tt.parent(); - if (p instanceof AST_ForIn && p.init === node) { + if (p instanceof Cola.AST_ForIn && p.init === node) { if (seq == null) return node.definitions[0].name; return seq; } - if (p instanceof AST_For && p.init === node) { + if (p instanceof Cola.AST_For && p.init === node) { return seq; } - if (!seq) return make_node(AST_EmptyStatement, node); - return make_node(AST_SimpleStatement, node, { + if (!seq) return make_node(Cola.AST_EmptyStatement, node); + return make_node(Cola.AST_SimpleStatement, node, { body: seq }); } - if (node instanceof AST_Scope) + if (node instanceof Cola.AST_Scope) return node; // to avoid descending in nested scopes } } @@ -1221,8 +1221,8 @@ merge(Compressor.prototype, { // collect only vars which don't show up in self's arguments list var defs = []; vars.each(function(def, name){ - if (self instanceof AST_Lambda - && find_if(function(x){ return x.name == def.name.name }, + if (self instanceof Cola.AST_Lambda + && Cola.find_if(function(x){ return x.name == def.name.name }, self.argnames)) { vars.del(name); } else { @@ -1235,48 +1235,48 @@ merge(Compressor.prototype, { if (defs.length > 0) { // try to merge in assignments for (var i = 0; i < self.body.length;) { - if (self.body[i] instanceof AST_SimpleStatement) { + if (self.body[i] instanceof Cola.AST_SimpleStatement) { var expr = self.body[i].body, sym, assign; - if (expr instanceof AST_Assign + if (expr instanceof Cola.AST_Assign && expr.operator == "=" - && (sym = expr.left) instanceof AST_Symbol + && (sym = expr.left) instanceof Cola.AST_Symbol && vars.has(sym.name)) { var def = vars.get(sym.name); if (def.value) break; def.value = expr.right; - remove(defs, def); + Cola.remove(defs, def); defs.push(def); self.body.splice(i, 1); continue; } - if (expr instanceof AST_Seq - && (assign = expr.car) instanceof AST_Assign + if (expr instanceof Cola.AST_Seq + && (assign = expr.car) instanceof Cola.AST_Assign && assign.operator == "=" - && (sym = assign.left) instanceof AST_Symbol + && (sym = assign.left) instanceof Cola.AST_Symbol && vars.has(sym.name)) { var def = vars.get(sym.name); if (def.value) break; def.value = assign.right; - remove(defs, def); + Cola.remove(defs, def); defs.push(def); self.body[i].body = expr.cdr; continue; } } - if (self.body[i] instanceof AST_EmptyStatement) { + if (self.body[i] instanceof Cola.AST_EmptyStatement) { self.body.splice(i, 1); continue; } - if (self.body[i] instanceof AST_BlockStatement) { + if (self.body[i] instanceof Cola.AST_BlockStatement) { var tmp = [ i, 1 ].concat(self.body[i].body); self.body.splice.apply(self.body, tmp); continue; } break; } - defs = make_node(AST_Var, self, { + defs = make_node(Cola.AST_Var, self, { definitions: defs }); hoisted.push(defs); @@ -1287,30 +1287,30 @@ merge(Compressor.prototype, { return self; }); - OPT(AST_SimpleStatement, function(self, compressor){ + OPT(Cola.AST_SimpleStatement, function(self, compressor){ if (compressor.option("side_effects")) { if (!self.body.has_side_effects(compressor)) { compressor.warn("Dropping side-effect-free statement [{file}:{line},{col}]", self.start); - return make_node(AST_EmptyStatement, self); + return make_node(Cola.AST_EmptyStatement, self); } } return self; }); - OPT(AST_DWLoop, function(self, compressor){ + OPT(Cola.AST_DWLoop, function(self, compressor){ var cond = self.condition.evaluate(compressor); self.condition = cond[0]; if (!compressor.option("loops")) return self; if (cond.length > 1) { if (cond[1]) { - return make_node(AST_For, self, { + return make_node(Cola.AST_For, self, { body: self.body }); - } else if (self instanceof AST_While) { + } else if (self instanceof Cola.AST_While) { if (compressor.option("dead_code")) { var a = []; extract_declarations_from_unreachable_code(compressor, self.body, a); - return make_node(AST_BlockStatement, self, { body: a }); + return make_node(Cola.AST_BlockStatement, self, { body: a }); } } } @@ -1320,23 +1320,23 @@ merge(Compressor.prototype, { function if_break_in_loop(self, compressor) { function drop_it(rest) { rest = as_statement_array(rest); - if (self.body instanceof AST_BlockStatement) { + if (self.body instanceof Cola.AST_BlockStatement) { self.body = self.body.clone(); self.body.body = rest.concat(self.body.body.slice(1)); self.body = self.body.transform(compressor); } else { - self.body = make_node(AST_BlockStatement, self.body, { + self.body = make_node(Cola.AST_BlockStatement, self.body, { body: rest }).transform(compressor); } if_break_in_loop(self, compressor); } - var first = self.body instanceof AST_BlockStatement ? self.body.body[0] : self.body; - if (first instanceof AST_If) { - if (first.body instanceof AST_Break + var first = self.body instanceof Cola.AST_BlockStatement ? self.body.body[0] : self.body; + if (first instanceof Cola.AST_If) { + if (first.body instanceof Cola.AST_Break && compressor.loopcontrol_target(first.body.label) === self) { if (self.condition) { - self.condition = make_node(AST_Binary, self.condition, { + self.condition = make_node(Cola.AST_Binary, self.condition, { left: self.condition, operator: "&&", right: first.condition.negate(compressor), @@ -1346,10 +1346,10 @@ merge(Compressor.prototype, { } drop_it(first.alternative); } - else if (first.alternative instanceof AST_Break + else if (first.alternative instanceof Cola.AST_Break && compressor.loopcontrol_target(first.alternative.label) === self) { if (self.condition) { - self.condition = make_node(AST_Binary, self.condition, { + self.condition = make_node(Cola.AST_Binary, self.condition, { left: self.condition, operator: "&&", right: first.condition, @@ -1362,17 +1362,17 @@ merge(Compressor.prototype, { } }; - OPT(AST_While, function(self, compressor) { + OPT(Cola.AST_While, function(self, compressor) { if (!compressor.option("loops")) return self; - self = AST_DWLoop.prototype.optimize.call(self, compressor); - if (self instanceof AST_While) { + self = Cola.AST_DWLoop.prototype.optimize.call(self, compressor); + if (self instanceof Cola.AST_While) { if_break_in_loop(self, compressor); - self = make_node(AST_For, self, self).transform(compressor); + self = make_node(Cola.AST_For, self, self).transform(compressor); } return self; }); - OPT(AST_For, function(self, compressor){ + OPT(Cola.AST_For, function(self, compressor){ var cond = self.condition; if (cond) { cond = cond.evaluate(compressor); @@ -1383,16 +1383,16 @@ merge(Compressor.prototype, { if (cond.length > 1 && !cond[1]) { if (compressor.option("dead_code")) { var a = []; - if (self.init instanceof AST_Statement) { + if (self.init instanceof Cola.AST_Statement) { a.push(self.init); } else if (self.init) { - a.push(make_node(AST_SimpleStatement, self.init, { + a.push(make_node(Cola.AST_SimpleStatement, self.init, { body: self.init })); } extract_declarations_from_unreachable_code(compressor, self.body, a); - return make_node(AST_BlockStatement, self, { body: a }); + return make_node(Cola.AST_BlockStatement, self, { body: a }); } } } @@ -1400,7 +1400,7 @@ merge(Compressor.prototype, { return self; }); - OPT(AST_If, function(self, compressor){ + OPT(Cola.AST_If, function(self, compressor){ if (!compressor.option("conditionals")) return self; // if condition can be statically determined, warn and drop // one of the blocks. note, statically determined implies @@ -1417,7 +1417,7 @@ merge(Compressor.prototype, { extract_declarations_from_unreachable_code(compressor, self.alternative, a); } a.push(self.body); - return make_node(AST_BlockStatement, self, { body: a }).transform(compressor); + return make_node(Cola.AST_BlockStatement, self, { body: a }).transform(compressor); } } else { compressor.warn("Condition always false [{file}:{line},{col}]", self.condition.start); @@ -1425,7 +1425,7 @@ merge(Compressor.prototype, { var a = []; extract_declarations_from_unreachable_code(compressor, self.body, a); if (self.alternative) a.push(self.alternative); - return make_node(AST_BlockStatement, self, { body: a }).transform(compressor); + return make_node(Cola.AST_BlockStatement, self, { body: a }).transform(compressor); } } } @@ -1436,66 +1436,66 @@ merge(Compressor.prototype, { negated_is_best = false; // because we already do the switch here. self.condition = negated; var tmp = self.body; - self.body = self.alternative || make_node(AST_EmptyStatement); + self.body = self.alternative || make_node(Cola.AST_EmptyStatement); self.alternative = tmp; } if (is_empty(self.body) && is_empty(self.alternative)) { - return make_node(AST_SimpleStatement, self.condition, { + return make_node(Cola.AST_SimpleStatement, self.condition, { body: self.condition }).transform(compressor); } - if (self.body instanceof AST_SimpleStatement - && self.alternative instanceof AST_SimpleStatement) { - return make_node(AST_SimpleStatement, self, { - body: make_node(AST_Conditional, self, { + if (self.body instanceof Cola.AST_SimpleStatement + && self.alternative instanceof Cola.AST_SimpleStatement) { + return make_node(Cola.AST_SimpleStatement, self, { + body: make_node(Cola.AST_Conditional, self, { condition : self.condition, consequent : self.body.body, alternative : self.alternative.body }) }).transform(compressor); } - if (is_empty(self.alternative) && self.body instanceof AST_SimpleStatement) { - if (negated_is_best) return make_node(AST_SimpleStatement, self, { - body: make_node(AST_Binary, self, { + if (is_empty(self.alternative) && self.body instanceof Cola.AST_SimpleStatement) { + if (negated_is_best) return make_node(Cola.AST_SimpleStatement, self, { + body: make_node(Cola.AST_Binary, self, { operator : "||", left : negated, right : self.body.body }) }).transform(compressor); - return make_node(AST_SimpleStatement, self, { - body: make_node(AST_Binary, self, { + return make_node(Cola.AST_SimpleStatement, self, { + body: make_node(Cola.AST_Binary, self, { operator : "&&", left : self.condition, right : self.body.body }) }).transform(compressor); } - if (self.body instanceof AST_EmptyStatement + if (self.body instanceof Cola.AST_EmptyStatement && self.alternative - && self.alternative instanceof AST_SimpleStatement) { - return make_node(AST_SimpleStatement, self, { - body: make_node(AST_Binary, self, { + && self.alternative instanceof Cola.AST_SimpleStatement) { + return make_node(Cola.AST_SimpleStatement, self, { + body: make_node(Cola.AST_Binary, self, { operator : "||", left : self.condition, right : self.alternative.body }) }).transform(compressor); } - if (self.body instanceof AST_Exit - && self.alternative instanceof AST_Exit + if (self.body instanceof Cola.AST_Exit + && self.alternative instanceof Cola.AST_Exit && self.body.TYPE == self.alternative.TYPE) { return make_node(self.body.CTOR, self, { - value: make_node(AST_Conditional, self, { + value: make_node(Cola.AST_Conditional, self, { condition : self.condition, - consequent : self.body.value || make_node(AST_Undefined, self.body).optimize(compressor), - alternative : self.alternative.value || make_node(AST_Undefined, self.alternative).optimize(compressor) + consequent : self.body.value || make_node(Cola.AST_Undefined, self.body).optimize(compressor), + alternative : self.alternative.value || make_node(Cola.AST_Undefined, self.alternative).optimize(compressor) }) }).transform(compressor); } - if (self.body instanceof AST_If + if (self.body instanceof Cola.AST_If && !self.body.alternative && !self.alternative) { - self.condition = make_node(AST_Binary, self.condition, { + self.condition = make_node(Cola.AST_Binary, self.condition, { operator: "&&", left: self.condition, right: self.body.condition @@ -1506,7 +1506,7 @@ merge(Compressor.prototype, { if (self.alternative) { var alt = self.alternative; self.alternative = null; - return make_node(AST_BlockStatement, self, { + return make_node(Cola.AST_BlockStatement, self, { body: [ self, alt ] }).transform(compressor); } @@ -1516,16 +1516,16 @@ merge(Compressor.prototype, { self.body = self.alternative; self.condition = negated_is_best ? negated : self.condition.negate(compressor); self.alternative = null; - return make_node(AST_BlockStatement, self, { + return make_node(Cola.AST_BlockStatement, self, { body: [ self, body ] }).transform(compressor); } return self; }); - OPT(AST_Switch, function(self, compressor){ + OPT(Cola.AST_Switch, function(self, compressor){ if (self.body.length == 0 && compressor.option("conditionals")) { - return make_node(AST_SimpleStatement, self, { + return make_node(Cola.AST_SimpleStatement, self, { body: self.expression }).transform(compressor); } @@ -1533,9 +1533,9 @@ merge(Compressor.prototype, { var last_branch = self.body[self.body.length - 1]; if (last_branch) { var stat = last_branch.body[last_branch.body.length - 1]; // last statement - if (stat instanceof AST_Break && loop_body(compressor.loopcontrol_target(stat.label)) === self) + if (stat instanceof Cola.AST_Break && loop_body(compressor.loopcontrol_target(stat.label)) === self) last_branch.body.pop(); - if (last_branch instanceof AST_Default && last_branch.body.length == 0) { + if (last_branch instanceof Cola.AST_Default && last_branch.body.length == 0) { self.body.pop(); continue; } @@ -1554,45 +1554,45 @@ merge(Compressor.prototype, { var stopped = false; var ruined = false; var tt = new TreeTransformer(function(node, descend, in_list){ - if (node instanceof AST_Lambda || node instanceof AST_SimpleStatement) { + if (node instanceof Cola.AST_Lambda || node instanceof Cola.AST_SimpleStatement) { // no need to descend these node types return node; } - else if (node instanceof AST_Switch && node === self) { + else if (node instanceof Cola.AST_Switch && node === self) { node = node.clone(); descend(node, this); - return ruined ? node : make_node(AST_BlockStatement, node, { + return ruined ? node : make_node(Cola.AST_BlockStatement, node, { body: node.body.reduce(function(a, branch){ return a.concat(branch.body); }, []) }).transform(compressor); } - else if (node instanceof AST_If || node instanceof AST_Try) { + else if (node instanceof Cola.AST_If || node instanceof Cola.AST_Try) { var save = in_if; in_if = !in_block; descend(node, this); in_if = save; return node; } - else if (node instanceof AST_StatementWithBody || node instanceof AST_Switch) { + else if (node instanceof Cola.AST_StatementWithBody || node instanceof Cola.AST_Switch) { var save = in_block; in_block = true; descend(node, this); in_block = save; return node; } - else if (node instanceof AST_Break && this.loopcontrol_target(node.label) === self) { + else if (node instanceof Cola.AST_Break && this.loopcontrol_target(node.label) === self) { if (in_if) { ruined = true; return node; } if (in_block) return node; stopped = true; - return in_list ? MAP.skip : make_node(AST_EmptyStatement, node); + return in_list ? Cola.MAP.skip : make_node(Cola.AST_EmptyStatement, node); } - else if (node instanceof AST_SwitchBranch && this.parent() === self) { - if (stopped) return MAP.skip; - if (node instanceof AST_Case) { + else if (node instanceof Cola.AST_SwitchBranch && this.parent() === self) { + if (stopped) return Cola.MAP.skip; + if (node instanceof Cola.AST_Case) { var exp = node.expression.evaluate(compressor); if (exp.length < 2) { // got a case with non-constant expression, baling out @@ -1604,7 +1604,7 @@ merge(Compressor.prototype, { descend(node, this); return node; } - return MAP.skip; + return Cola.MAP.skip; } descend(node, this); return node; @@ -1618,25 +1618,25 @@ merge(Compressor.prototype, { return self; }); - OPT(AST_Case, function(self, compressor){ + OPT(Cola.AST_Case, function(self, compressor){ self.body = tighten_body(self.body, compressor); return self; }); - OPT(AST_Try, function(self, compressor){ + OPT(Cola.AST_Try, function(self, compressor){ self.body = tighten_body(self.body, compressor); return self; }); - AST_Definitions.DEFMETHOD("remove_initializers", function(){ + Cola.AST_Definitions.DEFMETHOD("remove_initializers", function(){ this.definitions.forEach(function(def){ def.value = null }); }); - AST_Definitions.DEFMETHOD("to_assignments", function(){ + Cola.AST_Definitions.DEFMETHOD("to_assignments", function(){ var assignments = this.definitions.reduce(function(a, def){ if (def.value) { - var name = make_node(AST_SymbolRef, def.name, def.name); - a.push(make_node(AST_Assign, def, { + var name = make_node(Cola.AST_SymbolRef, def.name, def.name); + a.push(make_node(Cola.AST_Assign, def, { operator : "=", left : name, right : def.value @@ -1645,17 +1645,17 @@ merge(Compressor.prototype, { return a; }, []); if (assignments.length == 0) return null; - return AST_Seq.from_array(assignments); + return Cola.AST_Seq.from_array(assignments); }); - OPT(AST_Definitions, function(self, compressor){ + OPT(Cola.AST_Definitions, function(self, compressor){ if (self.definitions.length == 0) - return make_node(AST_EmptyStatement, self); + return make_node(Cola.AST_EmptyStatement, self); return self; }); - OPT(AST_Function, function(self, compressor){ - self = AST_Lambda.prototype.optimize.call(self, compressor); + OPT(Cola.AST_Function, function(self, compressor){ + self = Cola.AST_Lambda.prototype.optimize.call(self, compressor); if (compressor.option("unused")) { if (self.name && self.name.unreferenced()) { self.name = null; @@ -1664,47 +1664,47 @@ merge(Compressor.prototype, { return self; }); - OPT(AST_Call, function(self, compressor){ + OPT(Cola.AST_Call, function(self, compressor){ if (compressor.option("unsafe")) { var exp = self.expression; - if (exp instanceof AST_SymbolRef && exp.undeclared()) { + if (exp instanceof Cola.AST_SymbolRef && exp.undeclared()) { switch (exp.name) { case "Array": if (self.args.length != 1) { - return make_node(AST_Array, self, { + return make_node(Cola.AST_Array, self, { elements: self.args }).transform(compressor); } break; case "Object": if (self.args.length == 0) { - return make_node(AST_Object, self, { + return make_node(Cola.AST_Object, self, { properties: [] }); } break; case "String": - if (self.args.length == 0) return make_node(AST_String, self, { + if (self.args.length == 0) return make_node(Cola.AST_String, self, { value: "" }); - if (self.args.length <= 1) return make_node(AST_Binary, self, { + if (self.args.length <= 1) return make_node(Cola.AST_Binary, self, { left: self.args[0], operator: "+", - right: make_node(AST_String, self, { value: "" }) + right: make_node(Cola.AST_String, self, { value: "" }) }).transform(compressor); break; case "Number": - if (self.args.length == 0) return make_node(AST_Number, self, { + if (self.args.length == 0) return make_node(Cola.AST_Number, self, { value: 0 }); - if (self.args.length == 1) return make_node(AST_UnaryPrefix, self, { + if (self.args.length == 1) return make_node(Cola.AST_UnaryPrefix, self, { expression: self.args[0], operator: "+" }).transform(compressor); case "Boolean": - if (self.args.length == 0) return make_node(AST_False, self); - if (self.args.length == 1) return make_node(AST_UnaryPrefix, self, { - expression: make_node(AST_UnaryPrefix, null, { + if (self.args.length == 0) return make_node(Cola.AST_False, self); + if (self.args.length == 1) return make_node(Cola.AST_UnaryPrefix, self, { + expression: make_node(Cola.AST_UnaryPrefix, null, { expression: self.args[0], operator: "!" }), @@ -1712,7 +1712,7 @@ merge(Compressor.prototype, { }).transform(compressor); break; case "Function": - if (all(self.args, function(x){ return x instanceof AST_String })) { + if (Cola.all(self.args, function(x){ return x instanceof Cola.AST_String })) { // quite a corner-case, but we can handle it: // https://github.com/mishoo/UglifyJS2/issues/203 // if the code argument is a constant, then we can minify it. @@ -1720,7 +1720,7 @@ merge(Compressor.prototype, { var code = "(function(" + self.args.slice(0, -1).map(function(arg){ return arg.value; }).join(",") + "){" + self.args[self.args.length - 1].value + "})()"; - var ast = parse(code); + var ast = Cola.parse(code); ast.figure_out_scope({ screw_ie8: compressor.option("screw_ie8") }); var comp = new Compressor(compressor.options); ast = ast.transform(comp); @@ -1728,8 +1728,8 @@ merge(Compressor.prototype, { ast.mangle_names(); var fun; try { - ast.walk(new TreeWalker(function(node){ - if (node instanceof AST_Lambda) { + ast.walk(new Cola.TreeWalker(function(node){ + if (node instanceof Cola.AST_Lambda) { fun = node; throw ast; } @@ -1738,20 +1738,20 @@ merge(Compressor.prototype, { if (ex !== ast) throw ex; }; var args = fun.argnames.map(function(arg, i){ - return make_node(AST_String, self.args[i], { + return make_node(Cola.AST_String, self.args[i], { value: arg.print_to_string() }); }); var code = OutputStream(); - AST_BlockStatement.prototype._codegen.call(fun, fun, code); + Cola.AST_BlockStatement.prototype._codegen.call(fun, fun, code); code = code.toString().replace(/^\{|\}$/g, ""); - args.push(make_node(AST_String, self.args[self.args.length - 1], { + args.push(make_node(Cola.AST_String, self.args[self.args.length - 1], { value: code })); self.args = args; return self; } catch(ex) { - if (ex instanceof JS_Parse_Error) { + if (ex instanceof Cola.JS_Parse_Error) { compressor.warn("Error parsing code passed to new Function [{file}:{line},{col}]", self.args[self.args.length - 1].start); compressor.warn(ex.toString()); } else { @@ -1763,14 +1763,14 @@ merge(Compressor.prototype, { break; } } - else if (exp instanceof AST_Dot && exp.property == "toString" && self.args.length == 0) { - return make_node(AST_Binary, self, { - left: make_node(AST_String, self, { value: "" }), + else if (exp instanceof Cola.AST_Dot && exp.property == "toString" && self.args.length == 0) { + return make_node(Cola.AST_Binary, self, { + left: make_node(Cola.AST_String, self, { value: "" }), operator: "+", right: exp.expression }).transform(compressor); } - else if (exp instanceof AST_Dot && exp.expression instanceof AST_Array && exp.property == "join") EXIT: { + else if (exp instanceof Cola.AST_Dot && exp.expression instanceof Cola.AST_Array && exp.property == "join") EXIT: { var separator = self.args.length == 0 ? "," : self.args[0].evaluate(compressor)[1]; if (separator == null) break EXIT; // not a constant var elements = exp.expression.elements.reduce(function(a, el){ @@ -1789,18 +1789,18 @@ merge(Compressor.prototype, { } return a; }, []); - if (elements.length == 0) return make_node(AST_String, self, { value: "" }); + if (elements.length == 0) return make_node(Cola.AST_String, self, { value: "" }); if (elements.length == 1) return elements[0][0]; if (separator == "") { var first; - if (elements[0][0] instanceof AST_String - || elements[1][0] instanceof AST_String) { + if (elements[0][0] instanceof Cola.AST_String + || elements[1][0] instanceof Cola.AST_String) { first = elements.shift()[0]; } else { - first = make_node(AST_String, self, { value: "" }); + first = make_node(Cola.AST_String, self, { value: "" }); } return elements.reduce(function(prev, el){ - return make_node(AST_Binary, el[0], { + return make_node(Cola.AST_Binary, el[0], { operator : "+", left : prev, right : el[0], @@ -1819,41 +1819,41 @@ merge(Compressor.prototype, { } } if (compressor.option("side_effects")) { - if (self.expression instanceof AST_Function + if (self.expression instanceof Cola.AST_Function && self.args.length == 0 - && !AST_Block.prototype.has_side_effects.call(self.expression, compressor)) { - return make_node(AST_Undefined, self).transform(compressor); + && !Cola.AST_Block.prototype.has_side_effects.call(self.expression, compressor)) { + return make_node(Cola.AST_Undefined, self).transform(compressor); } } if (compressor.option("drop_console")) { - if (self.expression instanceof AST_PropAccess && - self.expression.expression instanceof AST_SymbolRef && + if (self.expression instanceof Cola.AST_PropAccess && + self.expression.expression instanceof Cola.AST_SymbolRef && self.expression.expression.name == "console" && self.expression.expression.undeclared()) { - return make_node(AST_Undefined, self).transform(compressor); + return make_node(Cola.AST_Undefined, self).transform(compressor); } } return self.evaluate(compressor)[0]; }); - OPT(AST_New, function(self, compressor){ + OPT(Cola.AST_New, function(self, compressor){ if (compressor.option("unsafe")) { var exp = self.expression; - if (exp instanceof AST_SymbolRef && exp.undeclared()) { + if (exp instanceof Cola.AST_SymbolRef && exp.undeclared()) { switch (exp.name) { case "Object": case "RegExp": case "Function": case "Error": case "Array": - return make_node(AST_Call, self, self).transform(compressor); + return make_node(Cola.AST_Call, self, self).transform(compressor); } } } return self; }); - OPT(AST_Seq, function(self, compressor){ + OPT(Cola.AST_Seq, function(self, compressor){ if (!compressor.option("side_effects")) return self; if (!self.car.has_side_effects(compressor)) { @@ -1861,21 +1861,21 @@ merge(Compressor.prototype, { // eval(something) because that changes the meaning of // eval (becomes lexical instead of global). var p; - if (!(self.cdr instanceof AST_SymbolRef + if (!(self.cdr instanceof Cola.AST_SymbolRef && self.cdr.name == "eval" && self.cdr.undeclared() - && (p = compressor.parent()) instanceof AST_Call + && (p = compressor.parent()) instanceof Cola.AST_Call && p.expression === self)) { return self.cdr; } } if (compressor.option("cascade")) { - if (self.car instanceof AST_Assign + if (self.car instanceof Cola.AST_Assign && !self.car.left.has_side_effects(compressor)) { if (self.car.left.equivalent_to(self.cdr)) { return self.car; } - if (self.cdr instanceof AST_Call + if (self.cdr instanceof Cola.AST_Call && self.cdr.expression.equivalent_to(self.car.left)) { self.cdr.expression = self.car; return self.cdr; @@ -1887,14 +1887,14 @@ merge(Compressor.prototype, { return self.car; } } - if (self.cdr instanceof AST_UnaryPrefix + if (self.cdr instanceof Cola.AST_UnaryPrefix && self.cdr.operator == "void" && !self.cdr.expression.has_side_effects(compressor)) { self.cdr.operator = self.car; return self.cdr; } - if (self.cdr instanceof AST_Undefined) { - return make_node(AST_UnaryPrefix, self, { + if (self.cdr instanceof Cola.AST_Undefined) { + return make_node(Cola.AST_UnaryPrefix, self, { operator : "void", expression : self.car }); @@ -1902,31 +1902,31 @@ merge(Compressor.prototype, { return self; }); - AST_Unary.DEFMETHOD("lift_sequences", function(compressor){ + Cola.AST_Unary.DEFMETHOD("lift_sequences", function(compressor){ if (compressor.option("sequences")) { - if (this.expression instanceof AST_Seq) { + if (this.expression instanceof Cola.AST_Seq) { var seq = this.expression; var x = seq.to_array(); this.expression = x.pop(); x.push(this); - seq = AST_Seq.from_array(x).transform(compressor); + seq = Cola.AST_Seq.from_array(x).transform(compressor); return seq; } } return this; }); - OPT(AST_UnaryPostfix, function(self, compressor){ + OPT(Cola.AST_UnaryPostfix, function(self, compressor){ return self.lift_sequences(compressor); }); - OPT(AST_UnaryPrefix, function(self, compressor){ + OPT(Cola.AST_UnaryPrefix, function(self, compressor){ self = self.lift_sequences(compressor); var e = self.expression; if (compressor.option("booleans") && compressor.in_boolean_context()) { switch (self.operator) { case "!": - if (e instanceof AST_UnaryPrefix && e.operator == "!") { + if (e instanceof Cola.AST_UnaryPrefix && e.operator == "!") { // !!foo ==> foo, if we're in boolean context return e.expression; } @@ -1935,9 +1935,9 @@ merge(Compressor.prototype, { // typeof always returns a non-empty string, thus it's // always true in booleans compressor.warn("Boolean expression always true [{file}:{line},{col}]", self.start); - return make_node(AST_True, self); + return make_node(Cola.AST_True, self); } - if (e instanceof AST_Binary && self.operator == "!") { + if (e instanceof Cola.AST_Binary && self.operator == "!") { self = best_of(self, e.negate(compressor)); } } @@ -1952,34 +1952,34 @@ merge(Compressor.prototype, { return ret; } - AST_Binary.DEFMETHOD("lift_sequences", function(compressor){ + Cola.AST_Binary.DEFMETHOD("lift_sequences", function(compressor){ if (compressor.option("sequences")) { - if (this.left instanceof AST_Seq) { + if (this.left instanceof Cola.AST_Seq) { var seq = this.left; var x = seq.to_array(); this.left = x.pop(); x.push(this); - seq = AST_Seq.from_array(x).transform(compressor); + seq = Cola.AST_Seq.from_array(x).transform(compressor); return seq; } - if (this.right instanceof AST_Seq - && this instanceof AST_Assign + if (this.right instanceof Cola.AST_Seq + && this instanceof Cola.AST_Assign && !has_side_effects_or_prop_access(this.left, compressor)) { var seq = this.right; var x = seq.to_array(); this.right = x.pop(); x.push(this); - seq = AST_Seq.from_array(x).transform(compressor); + seq = Cola.AST_Seq.from_array(x).transform(compressor); return seq; } } return this; }); - var commutativeOperators = makePredicate("== === != !== * & | ^"); + var commutativeOperators = Cola.makePredicate("== === != !== * & | ^"); - OPT(AST_Binary, function(self, compressor){ - var reverse = compressor.has_directive("use asm") ? noop + OPT(Cola.AST_Binary, function(self, compressor){ + var reverse = compressor.has_directive("use asm") ? Cola.noop : function(op, force) { if (force || !(self.left.has_side_effects(compressor) || self.right.has_side_effects(compressor))) { if (op) self.operator = op; @@ -1989,37 +1989,37 @@ merge(Compressor.prototype, { } }; if (commutativeOperators(self.operator)) { - if (self.right instanceof AST_Constant - && !(self.left instanceof AST_Constant)) { + if (self.right instanceof Cola.AST_Constant + && !(self.left instanceof Cola.AST_Constant)) { // if right is a constant, whatever side effects the // left side might have could not influence the // result. hence, force switch. - if (!(self.left instanceof AST_Binary - && PRECEDENCE[self.left.operator] >= PRECEDENCE[self.operator])) { + if (!(self.left instanceof Cola.AST_Binary + && Cola.PRECEDENCE[self.left.operator] >= Cola.PRECEDENCE[self.operator])) { reverse(null, true); } } if (/^[!=]==?$/.test(self.operator)) { - if (self.left instanceof AST_SymbolRef && self.right instanceof AST_Conditional) { - if (self.right.consequent instanceof AST_SymbolRef + if (self.left instanceof Cola.AST_SymbolRef && self.right instanceof Cola.AST_Conditional) { + if (self.right.consequent instanceof Cola.AST_SymbolRef && self.right.consequent.definition() === self.left.definition()) { if (/^==/.test(self.operator)) return self.right.condition; if (/^!=/.test(self.operator)) return self.right.condition.negate(compressor); } - if (self.right.alternative instanceof AST_SymbolRef + if (self.right.alternative instanceof Cola.AST_SymbolRef && self.right.alternative.definition() === self.left.definition()) { if (/^==/.test(self.operator)) return self.right.condition.negate(compressor); if (/^!=/.test(self.operator)) return self.right.condition; } } - if (self.right instanceof AST_SymbolRef && self.left instanceof AST_Conditional) { - if (self.left.consequent instanceof AST_SymbolRef + if (self.right instanceof Cola.AST_SymbolRef && self.left instanceof Cola.AST_Conditional) { + if (self.left.consequent instanceof Cola.AST_SymbolRef && self.left.consequent.definition() === self.right.definition()) { if (/^==/.test(self.operator)) return self.left.condition; if (/^!=/.test(self.operator)) return self.left.condition.negate(compressor); } - if (self.left.alternative instanceof AST_SymbolRef + if (self.left.alternative instanceof Cola.AST_SymbolRef && self.left.alternative.definition() === self.right.definition()) { if (/^==/.test(self.operator)) return self.left.condition.negate(compressor); if (/^!=/.test(self.operator)) return self.left.condition; @@ -2038,15 +2038,15 @@ merge(Compressor.prototype, { // XXX: intentionally falling down to the next case case "==": case "!=": - if (self.left instanceof AST_String + if (self.left instanceof Cola.AST_String && self.left.value == "undefined" - && self.right instanceof AST_UnaryPrefix + && self.right instanceof Cola.AST_UnaryPrefix && self.right.operator == "typeof" && compressor.option("unsafe")) { - if (!(self.right.expression instanceof AST_SymbolRef) + if (!(self.right.expression instanceof Cola.AST_SymbolRef) || !self.right.expression.undeclared()) { self.right = self.right.expression; - self.left = make_node(AST_Undefined, self.left).optimize(compressor); + self.left = make_node(Cola.AST_Undefined, self.left).optimize(compressor); if (self.operator.length == 2) self.operator += "="; } } @@ -2058,7 +2058,7 @@ merge(Compressor.prototype, { var rr = self.right.evaluate(compressor); if ((ll.length > 1 && !ll[1]) || (rr.length > 1 && !rr[1])) { compressor.warn("Boolean && always false [{file}:{line},{col}]", self.start); - return make_node(AST_False, self); + return make_node(Cola.AST_False, self); } if (ll.length > 1 && ll[1]) { return rr[0]; @@ -2072,7 +2072,7 @@ merge(Compressor.prototype, { var rr = self.right.evaluate(compressor); if ((ll.length > 1 && ll[1]) || (rr.length > 1 && rr[1])) { compressor.warn("Boolean || always true [{file}:{line},{col}]", self.start); - return make_node(AST_True, self); + return make_node(Cola.AST_True, self); } if (ll.length > 1 && !ll[1]) { return rr[0]; @@ -2084,17 +2084,17 @@ merge(Compressor.prototype, { case "+": var ll = self.left.evaluate(compressor); var rr = self.right.evaluate(compressor); - if ((ll.length > 1 && ll[0] instanceof AST_String && ll[1]) || - (rr.length > 1 && rr[0] instanceof AST_String && rr[1])) { + if ((ll.length > 1 && ll[0] instanceof Cola.AST_String && ll[1]) || + (rr.length > 1 && rr[0] instanceof Cola.AST_String && rr[1])) { compressor.warn("+ in boolean context always true [{file}:{line},{col}]", self.start); - return make_node(AST_True, self); + return make_node(Cola.AST_True, self); } break; } if (compressor.option("comparisons")) { - if (!(compressor.parent() instanceof AST_Binary) - || compressor.parent() instanceof AST_Assign) { - var negated = make_node(AST_UnaryPrefix, self, { + if (!(compressor.parent() instanceof Cola.AST_Binary) + || compressor.parent() instanceof Cola.AST_Assign) { + var negated = make_node(Cola.AST_UnaryPrefix, self, { operator: "!", expression: self.negate(compressor) }); @@ -2105,21 +2105,21 @@ merge(Compressor.prototype, { case "<=": reverse(">="); break; } } - if (self.operator == "+" && self.right instanceof AST_String - && self.right.getValue() === "" && self.left instanceof AST_Binary + if (self.operator == "+" && self.right instanceof Cola.AST_String + && self.right.getValue() === "" && self.left instanceof Cola.AST_Binary && self.left.operator == "+" && self.left.is_string(compressor)) { return self.left; } if (compressor.option("evaluate")) { if (self.operator == "+") { - if (self.left instanceof AST_Constant - && self.right instanceof AST_Binary + if (self.left instanceof Cola.AST_Constant + && self.right instanceof Cola.AST_Binary && self.right.operator == "+" - && self.right.left instanceof AST_Constant + && self.right.left instanceof Cola.AST_Constant && self.right.is_string(compressor)) { - self = make_node(AST_Binary, self, { + self = make_node(Cola.AST_Binary, self, { operator: "+", - left: make_node(AST_String, null, { + left: make_node(Cola.AST_String, null, { value: "" + self.left.getValue() + self.right.left.getValue(), start: self.left.start, end: self.right.left.end @@ -2127,35 +2127,35 @@ merge(Compressor.prototype, { right: self.right.right }); } - if (self.right instanceof AST_Constant - && self.left instanceof AST_Binary + if (self.right instanceof Cola.AST_Constant + && self.left instanceof Cola.AST_Binary && self.left.operator == "+" - && self.left.right instanceof AST_Constant + && self.left.right instanceof Cola.AST_Constant && self.left.is_string(compressor)) { - self = make_node(AST_Binary, self, { + self = make_node(Cola.AST_Binary, self, { operator: "+", left: self.left.left, - right: make_node(AST_String, null, { + right: make_node(Cola.AST_String, null, { value: "" + self.left.right.getValue() + self.right.getValue(), start: self.left.right.start, end: self.right.end }) }); } - if (self.left instanceof AST_Binary + if (self.left instanceof Cola.AST_Binary && self.left.operator == "+" && self.left.is_string(compressor) - && self.left.right instanceof AST_Constant - && self.right instanceof AST_Binary + && self.left.right instanceof Cola.AST_Constant + && self.right instanceof Cola.AST_Binary && self.right.operator == "+" - && self.right.left instanceof AST_Constant + && self.right.left instanceof Cola.AST_Constant && self.right.is_string(compressor)) { - self = make_node(AST_Binary, self, { + self = make_node(Cola.AST_Binary, self, { operator: "+", - left: make_node(AST_Binary, self.left, { + left: make_node(Cola.AST_Binary, self.left, { operator: "+", left: self.left.left, - right: make_node(AST_String, null, { + right: make_node(Cola.AST_String, null, { value: "" + self.left.right.getValue() + self.right.left.getValue(), start: self.left.right.start, end: self.right.left.end @@ -2167,11 +2167,11 @@ merge(Compressor.prototype, { } } // x * (y * z) ==> x * y * z - if (self.right instanceof AST_Binary + if (self.right instanceof Cola.AST_Binary && self.right.operator == self.operator && (self.operator == "*" || self.operator == "&&" || self.operator == "||")) { - self.left = make_node(AST_Binary, self.left, { + self.left = make_node(Cola.AST_Binary, self.left, { operator : self.operator, left : self.left, right : self.right.left @@ -2182,7 +2182,7 @@ merge(Compressor.prototype, { return self.evaluate(compressor)[0]; }); - OPT(AST_SymbolRef, function(self, compressor){ + OPT(Cola.AST_SymbolRef, function(self, compressor){ if (self.undeclared()) { var defines = compressor.option("global_defs"); if (defines && defines.hasOwnProperty(self.name)) { @@ -2190,22 +2190,22 @@ merge(Compressor.prototype, { } switch (self.name) { case "undefined": - return make_node(AST_Undefined, self); + return make_node(Cola.AST_Undefined, self); case "NaN": - return make_node(AST_NaN, self); + return make_node(Cola.AST_NaN, self); case "Infinity": - return make_node(AST_Infinity, self); + return make_node(Cola.AST_Infinity, self); } } return self; }); - OPT(AST_Undefined, function(self, compressor){ + OPT(Cola.AST_Undefined, function(self, compressor){ if (compressor.option("unsafe")) { - var scope = compressor.find_parent(AST_Scope); + var scope = compressor.find_parent(Cola.AST_Scope); var undef = scope.find_variable("undefined"); if (undef) { - var ref = make_node(AST_SymbolRef, self, { + var ref = make_node(Cola.AST_SymbolRef, self, { name : "undefined", scope : scope, thedef : undef @@ -2218,26 +2218,26 @@ merge(Compressor.prototype, { }); var ASSIGN_OPS = [ '+', '-', '/', '*', '%', '>>', '<<', '>>>', '|', '^', '&' ]; - OPT(AST_Assign, function(self, compressor){ + OPT(Cola.AST_Assign, function(self, compressor){ self = self.lift_sequences(compressor); if (self.operator == "=" - && self.left instanceof AST_SymbolRef - && self.right instanceof AST_Binary - && self.right.left instanceof AST_SymbolRef + && self.left instanceof Cola.AST_SymbolRef + && self.right instanceof Cola.AST_Binary + && self.right.left instanceof Cola.AST_SymbolRef && self.right.left.name == self.left.name - && member(self.right.operator, ASSIGN_OPS)) { + && Cola.member(self.right.operator, ASSIGN_OPS)) { self.operator = self.right.operator + "="; self.right = self.right.right; } return self; }); - OPT(AST_Conditional, function(self, compressor){ + OPT(Cola.AST_Conditional, function(self, compressor){ if (!compressor.option("conditionals")) return self; - if (self.condition instanceof AST_Seq) { + if (self.condition instanceof Cola.AST_Seq) { var car = self.condition.car; self.condition = self.condition.cdr; - return AST_Seq.cons(car, self); + return Cola.AST_Seq.cons(car, self); } var cond = self.condition.evaluate(compressor); if (cond.length > 1) { @@ -2251,7 +2251,7 @@ merge(Compressor.prototype, { } var negated = cond[0].negate(compressor); if (best_of(cond[0], negated) === negated) { - self = make_node(AST_Conditional, self, { + self = make_node(Cola.AST_Conditional, self, { condition: negated, consequent: self.alternative, alternative: self.consequent @@ -2259,8 +2259,8 @@ merge(Compressor.prototype, { } var consequent = self.consequent; var alternative = self.alternative; - if (consequent instanceof AST_Assign - && alternative instanceof AST_Assign + if (consequent instanceof Cola.AST_Assign + && alternative instanceof Cola.AST_Assign && consequent.operator == alternative.operator && consequent.left.equivalent_to(alternative.left) ) { @@ -2270,28 +2270,28 @@ merge(Compressor.prototype, { * ==> * exp = foo ? something : something_else; */ - return make_node(AST_Assign, self, { + return make_node(Cola.AST_Assign, self, { operator: consequent.operator, left: consequent.left, - right: make_node(AST_Conditional, self, { + right: make_node(Cola.AST_Conditional, self, { condition: self.condition, consequent: consequent.right, alternative: alternative.right }) }); } - if (consequent instanceof AST_Call + if (consequent instanceof Cola.AST_Call && alternative.TYPE === consequent.TYPE && consequent.args.length == alternative.args.length && consequent.expression.equivalent_to(alternative.expression)) { if (consequent.args.length == 0) { - return make_node(AST_Seq, self, { + return make_node(Cola.AST_Seq, self, { car: self.condition, cdr: consequent }); } if (consequent.args.length == 1) { - consequent.args[0] = make_node(AST_Conditional, self, { + consequent.args[0] = make_node(Cola.AST_Conditional, self, { condition: self.condition, consequent: consequent.args[0], alternative: alternative.args[0] @@ -2300,10 +2300,10 @@ merge(Compressor.prototype, { } } // x?y?z:a:a --> x&&y?z:a - if (consequent instanceof AST_Conditional + if (consequent instanceof Cola.AST_Conditional && consequent.alternative.equivalent_to(alternative)) { - return make_node(AST_Conditional, self, { - condition: make_node(AST_Binary, self, { + return make_node(Cola.AST_Conditional, self, { + condition: make_node(Cola.AST_Binary, self, { left: self.condition, operator: "&&", right: consequent.condition @@ -2315,10 +2315,10 @@ merge(Compressor.prototype, { return self; }); - OPT(AST_Boolean, function(self, compressor){ + OPT(Cola.AST_Boolean, function(self, compressor){ if (compressor.option("booleans")) { var p = compressor.parent(); - if (p instanceof AST_Binary && (p.operator == "==" + if (p instanceof Cola.AST_Binary && (p.operator == "==" || p.operator == "!=")) { compressor.warn("Non-strict equality against boolean: {operator} {value} [{file}:{line},{col}]", { operator : p.operator, @@ -2327,13 +2327,13 @@ merge(Compressor.prototype, { line : p.start.line, col : p.start.col, }); - return make_node(AST_Number, self, { + return make_node(Cola.AST_Number, self, { value: +self.value }); } - return make_node(AST_UnaryPrefix, self, { + return make_node(Cola.AST_UnaryPrefix, self, { operator: "!", - expression: make_node(AST_Number, self, { + expression: make_node(Cola.AST_Number, self, { value: 1 - self.value }) }); @@ -2341,19 +2341,19 @@ merge(Compressor.prototype, { return self; }); - OPT(AST_Sub, function(self, compressor){ + OPT(Cola.AST_Sub, function(self, compressor){ var prop = self.property; - if (prop instanceof AST_String && compressor.option("properties")) { + if (prop instanceof Cola.AST_String && compressor.option("properties")) { prop = prop.getValue(); - if (RESERVED_WORDS(prop) ? compressor.option("screw_ie8") : is_identifier_string(prop)) { - return make_node(AST_Dot, self, { + if (Cola.RESERVED_WORDS(prop) ? compressor.option("screw_ie8") : Cola.is_identifier_string(prop)) { + return make_node(Cola.AST_Dot, self, { expression : self.expression, property : prop }); } var v = parseFloat(prop); if (!isNaN(v) && v.toString() == prop) { - self.property = make_node(AST_Number, self.property, { + self.property = make_node(Cola.AST_Number, self.property, { value: v }); } @@ -2363,12 +2363,12 @@ merge(Compressor.prototype, { function literals_in_boolean_context(self, compressor) { if (compressor.option("booleans") && compressor.in_boolean_context()) { - return make_node(AST_True, self); + return make_node(Cola.AST_True, self); } return self; }; - OPT(AST_Array, literals_in_boolean_context); - OPT(AST_Object, literals_in_boolean_context); - OPT(AST_RegExp, literals_in_boolean_context); + OPT(Cola.AST_Array, literals_in_boolean_context); + OPT(Cola.AST_Object, literals_in_boolean_context); + OPT(Cola.AST_RegExp, literals_in_boolean_context); })(); diff --git a/lib/index.html b/lib/index.html index 80cda37f..450d0f70 100644 --- a/lib/index.html +++ b/lib/index.html @@ -65,7 +65,7 @@ try { // 1. compile - ast = parse(source); + ast = Cola.parse(source); ast = translate(ast); ast.print(stream); translationArea.value = stream.toString(); @@ -85,6 +85,8 @@ } catch(e){ translationArea.value = ''; resultArea.value = ''; + + throw e; } } @@ -94,7 +96,7 @@ function Translate(){ stream = OutputStream({ beautify : true }); - translate(parse(source)).print(stream); + translate(Cola.parse(source)).print(stream); return stream.toString(); } diff --git a/lib/mozilla-ast.js b/lib/mozilla-ast.js index d7950942..e93c3c48 100644 --- a/lib/mozilla-ast.js +++ b/lib/mozilla-ast.js @@ -47,16 +47,16 @@ var MOZ_TO_ME = { TryStatement : function(M) { - return new AST_Try({ + return new Cola.AST_Try({ start : my_start_token(M), end : my_end_token(M), body : from_moz(M.block).body, bcatch : from_moz(M.handlers[0]), - bfinally : M.finalizer ? new AST_Finally(from_moz(M.finalizer)) : null + bfinally : M.finalizer ? new Cola.AST_Finally(from_moz(M.finalizer)) : null }); }, CatchClause : function(M) { - return new AST_Catch({ + return new Cola.AST_Catch({ start : my_start_token(M), end : my_end_token(M), argname : from_moz(M.param), @@ -64,7 +64,7 @@ }); }, ObjectExpression : function(M) { - return new AST_Object({ + return new Cola.AST_Object({ start : my_start_token(M), end : my_end_token(M), properties : M.properties.map(function(prop){ @@ -78,22 +78,22 @@ }; switch (prop.kind) { case "init": - return new AST_ObjectKeyVal(args); + return new Cola.AST_ObjectKeyVal(args); case "set": args.value.name = from_moz(key); - return new AST_ObjectSetter(args); + return new Cola.AST_ObjectSetter(args); case "get": args.value.name = from_moz(key); - return new AST_ObjectGetter(args); + return new Cola.AST_ObjectGetter(args); } }) }); }, SequenceExpression : function(M) { - return AST_Seq.from_array(M.expressions.map(from_moz)); + return Cola.AST_Seq.from_array(M.expressions.map(from_moz)); }, MemberExpression : function(M) { - return new (M.computed ? AST_Sub : AST_Dot)({ + return new (M.computed ? Cola.AST_Sub : Cola.AST_Dot)({ start : my_start_token(M), end : my_end_token(M), property : M.computed ? from_moz(M.property) : M.property.name, @@ -101,7 +101,7 @@ }); }, SwitchCase : function(M) { - return new (M.test ? AST_Case : AST_Default)({ + return new (M.test ? Cola.AST_Case : Cola.AST_Default)({ start : my_start_token(M), end : my_end_token(M), expression : from_moz(M.test), @@ -113,33 +113,33 @@ start : my_start_token(M), end : my_end_token(M) }; - if (val === null) return new AST_Null(args); + if (val === null) return new Cola.AST_Null(args); switch (typeof val) { case "string": args.value = val; - return new AST_String(args); + return new Cola.AST_String(args); case "number": args.value = val; - return new AST_Number(args); + return new Cola.AST_Number(args); case "boolean": - return new (val ? AST_True : AST_False)(args); + return new (val ? Cola.AST_True : Cola.AST_False)(args); default: args.value = val; - return new AST_RegExp(args); + return new Cola.AST_RegExp(args); } }, UnaryExpression: From_Moz_Unary, UpdateExpression: From_Moz_Unary, Identifier: function(M) { var p = FROM_MOZ_STACK[FROM_MOZ_STACK.length - 2]; - return new (M.name == "this" ? AST_This - : p.type == "LabeledStatement" ? AST_Label - : p.type == "VariableDeclarator" && p.id === M ? (p.kind == "const" ? AST_SymbolConst : AST_SymbolVar) - : p.type == "FunctionExpression" ? (p.id === M ? AST_SymbolLambda : AST_SymbolFunarg) - : p.type == "FunctionDeclaration" ? (p.id === M ? AST_SymbolDefun : AST_SymbolFunarg) - : p.type == "CatchClause" ? AST_SymbolCatch - : p.type == "BreakStatement" || p.type == "ContinueStatement" ? AST_LabelRef - : AST_SymbolRef)({ + return new (M.name == "this" ? Cola.AST_This + : p.type == "LabeledStatement" ? Cola.AST_Label + : p.type == "VariableDeclarator" && p.id === M ? (p.kind == "const" ? Cola.AST_SymbolConst : Cola.AST_SymbolVar) + : p.type == "FunctionExpression" ? (p.id === M ? Cola.AST_SymbolLambda : Cola.AST_SymbolFunarg) + : p.type == "FunctionDeclaration" ? (p.id === M ? Cola.AST_SymbolDefun : Cola.AST_SymbolFunarg) + : p.type == "CatchClause" ? Cola.AST_SymbolCatch + : p.type == "BreakStatement" || p.type == "ContinueStatement" ? Cola.AST_LabelRef + : Cola.AST_SymbolRef)({ start : my_start_token(M), end : my_end_token(M), name : M.name @@ -150,7 +150,7 @@ function From_Moz_Unary(M) { var prefix = "prefix" in M ? M.prefix : M.type == "UnaryExpression" ? true : false; - return new (prefix ? AST_UnaryPrefix : AST_UnaryPostfix)({ + return new (prefix ? Cola.AST_UnaryPrefix : Cola.AST_UnaryPostfix)({ start : my_start_token(M), end : my_end_token(M), operator : M.operator, @@ -160,43 +160,43 @@ var ME_TO_MOZ = {}; - map("Node", AST_Node); - map("Program", AST_Toplevel, "body@body"); - map("Function", AST_Function, "id>name, params@argnames, body%body"); - map("EmptyStatement", AST_EmptyStatement); - map("BlockStatement", AST_BlockStatement, "body@body"); - map("ExpressionStatement", AST_SimpleStatement, "expression>body"); - map("IfStatement", AST_If, "test>condition, consequent>body, alternate>alternative"); - map("LabeledStatement", AST_LabeledStatement, "label>label, body>body"); - map("BreakStatement", AST_Break, "label>label"); - map("ContinueStatement", AST_Continue, "label>label"); - map("WithStatement", AST_With, "object>expression, body>body"); - map("SwitchStatement", AST_Switch, "discriminant>expression, cases@body"); - map("ReturnStatement", AST_Return, "argument>value"); - map("ThrowStatement", AST_Throw, "argument>value"); - map("WhileStatement", AST_While, "test>condition, body>body"); - map("DoWhileStatement", AST_Do, "test>condition, body>body"); - map("ForStatement", AST_For, "init>init, test>condition, update>step, body>body"); - map("ForInStatement", AST_ForIn, "left>init, right>object, body>body"); - map("DebuggerStatement", AST_Debugger); - map("FunctionDeclaration", AST_Defun, "id>name, params@argnames, body%body"); - map("VariableDeclaration", AST_Var, "declarations@definitions"); - map("VariableDeclarator", AST_VarDef, "id>name, init>value"); + map("Node", Cola.AST_Node); + map("Program", Cola.AST_Toplevel, "body@body"); + map("Function", Cola.AST_Function, "id>name, params@argnames, body%body"); + map("EmptyStatement", Cola.AST_EmptyStatement); + map("BlockStatement", Cola.AST_BlockStatement, "body@body"); + map("ExpressionStatement", Cola.AST_SimpleStatement, "expression>body"); + map("IfStatement", Cola.AST_If, "test>condition, consequent>body, alternate>alternative"); + map("LabeledStatement", Cola.AST_LabeledStatement, "label>label, body>body"); + map("BreakStatement", Cola.AST_Break, "label>label"); + map("ContinueStatement", Cola.AST_Continue, "label>label"); + map("WithStatement", Cola.AST_With, "object>expression, body>body"); + map("SwitchStatement", Cola.AST_Switch, "discriminant>expression, cases@body"); + map("ReturnStatement", Cola.AST_Return, "argument>value"); + map("ThrowStatement", Cola.AST_Throw, "argument>value"); + map("WhileStatement", Cola.AST_While, "test>condition, body>body"); + map("DoWhileStatement", Cola.AST_Do, "test>condition, body>body"); + map("ForStatement", Cola.AST_For, "init>init, test>condition, update>step, body>body"); + map("ForInStatement", Cola.AST_ForIn, "left>init, right>object, body>body"); + map("DebuggerStatement", Cola.AST_Debugger); + map("FunctionDeclaration", Cola.AST_Defun, "id>name, params@argnames, body%body"); + map("VariableDeclaration", Cola.AST_Var, "declarations@definitions"); + map("VariableDeclarator", Cola.AST_VarDef, "id>name, init>value"); - map("ThisExpression", AST_This); - map("ArrayExpression", AST_Array, "elements@elements"); - map("FunctionExpression", AST_Function, "id>name, params@argnames, body%body"); - map("BinaryExpression", AST_Binary, "operator=operator, left>left, right>right"); - map("AssignmentExpression", AST_Assign, "operator=operator, left>left, right>right"); - map("LogicalExpression", AST_Binary, "operator=operator, left>left, right>right"); - map("ConditionalExpression", AST_Conditional, "test>condition, consequent>consequent, alternate>alternative"); - map("NewExpression", AST_New, "callee>expression, arguments@args"); - map("CallExpression", AST_Call, "callee>expression, arguments@args"); + map("ThisExpression", Cola.AST_This); + map("ArrayExpression", Cola.AST_Array, "elements@elements"); + map("FunctionExpression", Cola.AST_Function, "id>name, params@argnames, body%body"); + map("BinaryExpression", Cola.AST_Binary, "operator=operator, left>left, right>right"); + map("AssignmentExpression", Cola.AST_Assign, "operator=operator, left>left, right>right"); + map("LogicalExpression", Cola.AST_Binary, "operator=operator, left>left, right>right"); + map("ConditionalExpression", Cola.AST_Conditional, "test>condition, consequent>consequent, alternate>alternative"); + map("NewExpression", Cola.AST_New, "callee>expression, arguments@args"); + map("CallExpression", Cola.AST_Call, "callee>expression, arguments@args"); /* -----[ tools ]----- */ function my_start_token(moznode) { - return new AST_Token({ + return new Cola.AST_Token({ file : moznode.loc && moznode.loc.source, line : moznode.loc && moznode.loc.start.line, col : moznode.loc && moznode.loc.start.column, @@ -206,7 +206,7 @@ }; function my_end_token(moznode) { - return new AST_Token({ + return new Cola.AST_Token({ file : moznode.loc && moznode.loc.source, line : moznode.loc && moznode.loc.end.line, col : moznode.loc && moznode.loc.end.column, @@ -256,7 +256,7 @@ return ret; }; - AST_Node.from_mozilla_ast = function(node){ + Cola.AST_Node.from_mozilla_ast = function(node){ var save_stack = FROM_MOZ_STACK; FROM_MOZ_STACK = []; var ast = from_moz(node); diff --git a/lib/output.js b/lib/output.js index adbc9a41..990ce993 100644 --- a/lib/output.js +++ b/lib/output.js @@ -45,7 +45,7 @@ function OutputStream(options) { - options = defaults(options, { + options = Cola.defaults(options, { indent_start : 0, indent_level : 4, quote_keys : false, @@ -121,7 +121,7 @@ function OutputStream(options) { }; function make_indent(back) { - return repeat_string(" ", options.indent_start + indentation - back * options.indent_level); + return Cola.repeat_string(" ", options.indent_start + indentation - back * options.indent_level); }; /* -----[ beautification/minification ]----- */ @@ -139,7 +139,7 @@ function OutputStream(options) { print("\n"); }; - var requireSemicolonChars = makePredicate("( [ + * / - , ."); + var requireSemicolonChars = Cola.makePredicate("( [ + * / - , ."); function print(str) { str = String(str); @@ -176,8 +176,8 @@ function OutputStream(options) { if (might_need_space) { var prev = last_char(); - if ((is_identifier_char(prev) - && (is_identifier_char(ch) || ch == "\\")) + if ((Cola.is_identifier_char(prev) + && (Cola.is_identifier_char(ch) || ch == "\\")) || (/^[\+\-\/]$/.test(ch) && ch == prev)) { OUTPUT += " "; @@ -208,7 +208,7 @@ function OutputStream(options) { if (options.beautify) { print(make_indent(half ? 0.5 : 0)); } - } : noop; + } : Cola.noop; var with_indent = options.beautify ? function(col, cont) { if (col === true) col = next_indent(); @@ -221,7 +221,7 @@ function OutputStream(options) { var newline = options.beautify ? function() { print("\n"); - } : noop; + } : Cola.noop; var semicolon = options.beautify ? function() { print(";"); @@ -286,7 +286,7 @@ function OutputStream(options) { (!name && token.type == "name") ? token.value : name ); } catch(ex) { - AST_Node.warn("Couldn't figure out mapping for {file}:{line},{col} → {cline},{ccol} [{name}]", { + Cola.AST_Node.warn("Couldn't figure out mapping for {file}:{line},{col} → {cline},{ccol} [{name}]", { file: token.file, line: token.line, col: token.col, @@ -295,7 +295,7 @@ function OutputStream(options) { name: name || "" }) } - } : noop; + } : Cola.noop; function get() { return OUTPUT; @@ -354,7 +354,7 @@ function OutputStream(options) { nodetype.DEFMETHOD("_codegen", generator); }; - AST_Node.DEFMETHOD("print", function(stream, force_parens){ + Cola.AST_Node.DEFMETHOD("print", function(stream, force_parens){ var self = this, generator = self._codegen; function doit() { self.add_comments(stream); @@ -370,7 +370,7 @@ function OutputStream(options) { stream.pop_node(); }); - AST_Node.DEFMETHOD("print_to_string", function(options){ + Cola.AST_Node.DEFMETHOD("print_to_string", function(options){ var s = OutputStream(options); this.print(s); return s.get(); @@ -378,7 +378,7 @@ function OutputStream(options) { /* -----[ comments ]----- */ - AST_Node.DEFMETHOD("add_comments", function(output){ + Cola.AST_Node.DEFMETHOD("add_comments", function(output){ var c = output.option("comments"), self = this; if (c) { var start = self.start; @@ -388,15 +388,15 @@ function OutputStream(options) { // XXX: ugly fix for https://github.com/mishoo/UglifyJS2/issues/112 // and https://github.com/mishoo/UglifyJS2/issues/372 - if (self instanceof AST_Exit && self.value) { - self.value.walk(new TreeWalker(function(node){ + if (self instanceof Cola.AST_Exit && self.value) { + self.value.walk(new Cola.TreeWalker(function(node){ if (node.start && node.start.comments_before) { comments = comments.concat(node.start.comments_before); node.start.comments_before = []; } - if (node instanceof AST_Function || - node instanceof AST_Array || - node instanceof AST_Object) + if (node instanceof Cola.AST_Function || + node instanceof Cola.AST_Array || + node instanceof Cola.AST_Object) { return true; // don't go inside. } @@ -437,56 +437,56 @@ function OutputStream(options) { nodetype.DEFMETHOD("needs_parens", func); }; - PARENS(AST_Node, function(){ + PARENS(Cola.AST_Node, function(){ return false; }); // a function expression needs parens around it when it's provably // the first token to appear in a statement. - PARENS(AST_Function, function(output){ + PARENS(Cola.AST_Function, function(output){ return first_in_statement(output); }); // same goes for an object literal, because otherwise it would be // interpreted as a block of code. - PARENS(AST_Object, function(output){ + PARENS(Cola.AST_Object, function(output){ return first_in_statement(output); }); - PARENS(AST_Unary, function(output){ + PARENS(Cola.AST_Unary, function(output){ var p = output.parent(); - return p instanceof AST_PropAccess && p.expression === this; + return p instanceof Cola.AST_PropAccess && p.expression === this; }); - PARENS(AST_Seq, function(output){ + PARENS(Cola.AST_Seq, function(output){ var p = output.parent(); - return p instanceof AST_Call // (foo, bar)() or foo(1, (2, 3), 4) - || p instanceof AST_Unary // !(foo, bar, baz) - || p instanceof AST_Binary // 1 + (2, 3) + 4 ==> 8 - || p instanceof AST_VarDef // var a = (1, 2), b = a + a; ==> b == 4 - || p instanceof AST_PropAccess // (1, {foo:2}).foo or (1, {foo:2})["foo"] ==> 2 - || p instanceof AST_Array // [ 1, (2, 3), 4 ] ==> [ 1, 3, 4 ] - || p instanceof AST_ObjectProperty // { foo: (1, 2) }.foo ==> 2 - || p instanceof AST_Conditional /* (false, true) ? (a = 10, b = 20) : (c = 30) + return p instanceof Cola.AST_Call // (foo, bar)() or foo(1, (2, 3), 4) + || p instanceof Cola.AST_Unary // !(foo, bar, baz) + || p instanceof Cola.AST_Binary // 1 + (2, 3) + 4 ==> 8 + || p instanceof Cola.AST_VarDef // var a = (1, 2), b = a + a; ==> b == 4 + || p instanceof Cola.AST_PropAccess // (1, {foo:2}).foo or (1, {foo:2})["foo"] ==> 2 + || p instanceof Cola.AST_Array // [ 1, (2, 3), 4 ] ==> [ 1, 3, 4 ] + || p instanceof Cola.AST_ObjectProperty // { foo: (1, 2) }.foo ==> 2 + || p instanceof Cola.AST_Conditional /* (false, true) ? (a = 10, b = 20) : (c = 30) * ==> 20 (side effect, set a := 10 and b := 20) */ ; }); - PARENS(AST_Binary, function(output){ + PARENS(Cola.AST_Binary, function(output){ var p = output.parent(); // (foo && bar)() - if (p instanceof AST_Call && p.expression === this) + if (p instanceof Cola.AST_Call && p.expression === this) return true; // typeof (foo && bar) - if (p instanceof AST_Unary) + if (p instanceof Cola.AST_Unary) return true; // (foo && bar)["prop"], (foo && bar).prop - if (p instanceof AST_PropAccess && p.expression === this) + if (p instanceof Cola.AST_PropAccess && p.expression === this) return true; // this deals with precedence: 3 * (2 + 1) - if (p instanceof AST_Binary) { - var po = p.operator, pp = PRECEDENCE[po]; - var so = this.operator, sp = PRECEDENCE[so]; + if (p instanceof Cola.AST_Binary) { + var po = p.operator, pp = Cola.PRECEDENCE[po]; + var so = this.operator, sp = Cola.PRECEDENCE[so]; if (pp > sp || (pp == sp && this === p.right)) { @@ -495,9 +495,9 @@ function OutputStream(options) { } }); - PARENS(AST_PropAccess, function(output){ + PARENS(Cola.AST_PropAccess, function(output){ var p = output.parent(); - if (p instanceof AST_New && p.expression === this) { + if (p instanceof Cola.AST_New && p.expression === this) { // i.e. new (foo.bar().baz) // // if there's one call into this subtree, then we need @@ -505,8 +505,8 @@ function OutputStream(options) { // interpreted as passing the arguments to the upper New // expression. try { - this.walk(new TreeWalker(function(node){ - if (node instanceof AST_Call) throw p; + this.walk(new Cola.TreeWalker(function(node){ + if (node instanceof Cola.AST_Call) throw p; })); } catch(ex) { if (ex !== p) throw ex; @@ -515,69 +515,69 @@ function OutputStream(options) { } }); - PARENS(AST_Call, function(output){ + PARENS(Cola.AST_Call, function(output){ var p = output.parent(), p1; - if (p instanceof AST_New && p.expression === this) + if (p instanceof Cola.AST_New && p.expression === this) return true; // workaround for Safari bug. // https://bugs.webkit.org/show_bug.cgi?id=123506 - return this.expression instanceof AST_Function - && p instanceof AST_PropAccess + return this.expression instanceof Cola.AST_Function + && p instanceof Cola.AST_PropAccess && p.expression === this - && (p1 = output.parent(1)) instanceof AST_Assign + && (p1 = output.parent(1)) instanceof Cola.AST_Assign && p1.left === p; }); - PARENS(AST_New, function(output){ + PARENS(Cola.AST_New, function(output){ var p = output.parent(); if (no_constructor_parens(this, output) - && (p instanceof AST_PropAccess // (new Date).getTime(), (new Date)["getTime"]() - || p instanceof AST_Call && p.expression === this)) // (new foo)(bar) + && (p instanceof Cola.AST_PropAccess // (new Date).getTime(), (new Date)["getTime"]() + || p instanceof Cola.AST_Call && p.expression === this)) // (new foo)(bar) return true; }); - PARENS(AST_Number, function(output){ + PARENS(Cola.AST_Number, function(output){ var p = output.parent(); - if (this.getValue() < 0 && p instanceof AST_PropAccess && p.expression === this) + if (this.getValue() < 0 && p instanceof Cola.AST_PropAccess && p.expression === this) return true; }); - PARENS(AST_NaN, function(output){ + PARENS(Cola.AST_NaN, function(output){ var p = output.parent(); - if (p instanceof AST_PropAccess && p.expression === this) + if (p instanceof Cola.AST_PropAccess && p.expression === this) return true; }); function assign_and_conditional_paren_rules(output) { var p = output.parent(); // !(a = false) → true - if (p instanceof AST_Unary) + if (p instanceof Cola.AST_Unary) return true; // 1 + (a = 2) + 3 → 6, side effect setting a = 2 - if (p instanceof AST_Binary && !(p instanceof AST_Assign)) + if (p instanceof Cola.AST_Binary && !(p instanceof Cola.AST_Assign)) return true; // (a = func)() —or— new (a = Object)() - if (p instanceof AST_Call && p.expression === this) + if (p instanceof Cola.AST_Call && p.expression === this) return true; // (a = foo) ? bar : baz - if (p instanceof AST_Conditional && p.condition === this) + if (p instanceof Cola.AST_Conditional && p.condition === this) return true; // (a = foo)["prop"] —or— (a = foo).prop - if (p instanceof AST_PropAccess && p.expression === this) + if (p instanceof Cola.AST_PropAccess && p.expression === this) return true; }; - PARENS(AST_Assign, assign_and_conditional_paren_rules); - PARENS(AST_Conditional, assign_and_conditional_paren_rules); + PARENS(Cola.AST_Assign, assign_and_conditional_paren_rules); + PARENS(Cola.AST_Conditional, assign_and_conditional_paren_rules); /* -----[ PRINTERS ]----- */ - DEFPRINT(AST_Directive, function(self, output){ + DEFPRINT(Cola.AST_Directive, function(self, output){ output.print_string(self.value); output.semicolon(); }); - DEFPRINT(AST_Debugger, function(self, output){ + DEFPRINT(Cola.AST_Debugger, function(self, output){ output.print("debugger"); output.semicolon(); }); @@ -587,7 +587,7 @@ function OutputStream(options) { function display_body(body, is_toplevel, output) { var last = body.length - 1; body.forEach(function(stmt, i){ - if (!(stmt instanceof AST_EmptyStatement)) { + if (!(stmt instanceof Cola.AST_EmptyStatement)) { output.indent(); stmt.print(output); if (!(i == last && is_toplevel)) { @@ -598,24 +598,24 @@ function OutputStream(options) { }); }; - AST_StatementWithBody.DEFMETHOD("_do_print_body", function(output){ + Cola.AST_StatementWithBody.DEFMETHOD("_do_print_body", function(output){ force_statement(this.body, output); }); - DEFPRINT(AST_Statement, function(self, output){ + DEFPRINT(Cola.AST_Statement, function(self, output){ self.body.print(output); output.semicolon(); }); - DEFPRINT(AST_Toplevel, function(self, output){ + DEFPRINT(Cola.AST_Toplevel, function(self, output){ display_body(self.body, true, output); output.print(""); }); - DEFPRINT(AST_LabeledStatement, function(self, output){ + DEFPRINT(Cola.AST_LabeledStatement, function(self, output){ self.label.print(output); output.colon(); self.body.print(output); }); - DEFPRINT(AST_SimpleStatement, function(self, output){ + DEFPRINT(Cola.AST_SimpleStatement, function(self, output){ self.body.print(output); output.semicolon(); }); @@ -625,13 +625,13 @@ function OutputStream(options) { }); else output.print("{}"); }; - DEFPRINT(AST_BlockStatement, function(self, output){ + DEFPRINT(Cola.AST_BlockStatement, function(self, output){ print_bracketed(self.body, output); }); - DEFPRINT(AST_EmptyStatement, function(self, output){ + DEFPRINT(Cola.AST_EmptyStatement, function(self, output){ output.semicolon(); }); - DEFPRINT(AST_Do, function(self, output){ + DEFPRINT(Cola.AST_Do, function(self, output){ output.print("do"); output.space(); self._do_print_body(output); @@ -643,7 +643,7 @@ function OutputStream(options) { }); output.semicolon(); }); - DEFPRINT(AST_While, function(self, output){ + DEFPRINT(Cola.AST_While, function(self, output){ output.print("while"); output.space(); output.with_parens(function(){ @@ -652,12 +652,12 @@ function OutputStream(options) { output.space(); self._do_print_body(output); }); - DEFPRINT(AST_For, function(self, output){ + DEFPRINT(Cola.AST_For, function(self, output){ output.print("for"); output.space(); output.with_parens(function(){ if (self.init) { - if (self.init instanceof AST_Definitions) { + if (self.init instanceof Cola.AST_Definitions) { self.init.print(output); } else { parenthesize_for_noin(self.init, output, true); @@ -681,7 +681,7 @@ function OutputStream(options) { output.space(); self._do_print_body(output); }); - DEFPRINT(AST_ForIn, function(self, output){ + DEFPRINT(Cola.AST_ForIn, function(self, output){ output.print("for"); output.space(); output.with_parens(function(){ @@ -694,7 +694,7 @@ function OutputStream(options) { output.space(); self._do_print_body(output); }); - DEFPRINT(AST_With, function(self, output){ + DEFPRINT(Cola.AST_With, function(self, output){ output.print("with"); output.space(); output.with_parens(function(){ @@ -705,7 +705,7 @@ function OutputStream(options) { }); /* -----[ functions ]----- */ - AST_Lambda.DEFMETHOD("_do_print", function(output, nokeyword){ + Cola.AST_Lambda.DEFMETHOD("_do_print", function(output, nokeyword){ var self = this; if (!nokeyword) { output.print("function"); @@ -723,12 +723,12 @@ function OutputStream(options) { output.space(); print_bracketed(self.body, output); }); - DEFPRINT(AST_Lambda, function(self, output){ + DEFPRINT(Cola.AST_Lambda, function(self, output){ self._do_print(output); }); /* -----[ exits ]----- */ - AST_Exit.DEFMETHOD("_do_print", function(output, kind){ + Cola.AST_Exit.DEFMETHOD("_do_print", function(output, kind){ output.print(kind); if (this.value) { output.space(); @@ -736,15 +736,15 @@ function OutputStream(options) { } output.semicolon(); }); - DEFPRINT(AST_Return, function(self, output){ + DEFPRINT(Cola.AST_Return, function(self, output){ self._do_print(output, "return"); }); - DEFPRINT(AST_Throw, function(self, output){ + DEFPRINT(Cola.AST_Throw, function(self, output){ self._do_print(output, "throw"); }); /* -----[ loop control ]----- */ - AST_LoopControl.DEFMETHOD("_do_print", function(output, kind){ + Cola.AST_LoopControl.DEFMETHOD("_do_print", function(output, kind){ output.print(kind); if (this.label) { output.space(); @@ -752,10 +752,10 @@ function OutputStream(options) { } output.semicolon(); }); - DEFPRINT(AST_Break, function(self, output){ + DEFPRINT(Cola.AST_Break, function(self, output){ self._do_print(output, "break"); }); - DEFPRINT(AST_Continue, function(self, output){ + DEFPRINT(Cola.AST_Continue, function(self, output){ self._do_print(output, "continue"); }); @@ -774,7 +774,7 @@ function OutputStream(options) { // adds the block brackets if needed. if (!self.body) return output.force_semicolon(); - if (self.body instanceof AST_Do + if (self.body instanceof Cola.AST_Do && !output.option("screw_ie8")) { // https://github.com/mishoo/UglifyJS/issues/#issue/57 IE // croaks with "syntax error" on code like this: if (foo) @@ -785,21 +785,21 @@ function OutputStream(options) { } var b = self.body; while (true) { - if (b instanceof AST_If) { + if (b instanceof Cola.AST_If) { if (!b.alternative) { make_block(self.body, output); return; } b = b.alternative; } - else if (b instanceof AST_StatementWithBody) { + else if (b instanceof Cola.AST_StatementWithBody) { b = b.body; } else break; } force_statement(self.body, output); }; - DEFPRINT(AST_If, function(self, output){ + DEFPRINT(Cola.AST_If, function(self, output){ output.print("if"); output.space(); output.with_parens(function(){ @@ -818,7 +818,7 @@ function OutputStream(options) { }); /* -----[ switch ]----- */ - DEFPRINT(AST_Switch, function(self, output){ + DEFPRINT(Cola.AST_Switch, function(self, output){ output.print("switch"); output.space(); output.with_parens(function(){ @@ -834,7 +834,7 @@ function OutputStream(options) { }); else output.print("{}"); }); - AST_SwitchBranch.DEFMETHOD("_do_print_body", function(output){ + Cola.AST_SwitchBranch.DEFMETHOD("_do_print_body", function(output){ if (this.body.length > 0) { output.newline(); this.body.forEach(function(stmt){ @@ -844,11 +844,11 @@ function OutputStream(options) { }); } }); - DEFPRINT(AST_Default, function(self, output){ + DEFPRINT(Cola.AST_Default, function(self, output){ output.print("default:"); self._do_print_body(output); }); - DEFPRINT(AST_Case, function(self, output){ + DEFPRINT(Cola.AST_Case, function(self, output){ output.print("case"); output.space(); self.expression.print(output); @@ -857,7 +857,7 @@ function OutputStream(options) { }); /* -----[ exceptions ]----- */ - DEFPRINT(AST_Try, function(self, output){ + DEFPRINT(Cola.AST_Try, function(self, output){ output.print("try"); output.space(); print_bracketed(self.body, output); @@ -870,7 +870,7 @@ function OutputStream(options) { self.bfinally.print(output); } }); - DEFPRINT(AST_Catch, function(self, output){ + DEFPRINT(Cola.AST_Catch, function(self, output){ output.print("catch"); output.space(); output.with_parens(function(){ @@ -879,14 +879,14 @@ function OutputStream(options) { output.space(); print_bracketed(self.body, output); }); - DEFPRINT(AST_Finally, function(self, output){ + DEFPRINT(Cola.AST_Finally, function(self, output){ output.print("finally"); output.space(); print_bracketed(self.body, output); }); /* -----[ var/const ]----- */ - AST_Definitions.DEFMETHOD("_do_print", function(output, kind){ + Cola.AST_Definitions.DEFMETHOD("_do_print", function(output, kind){ output.print(kind); output.space(); this.definitions.forEach(function(def, i){ @@ -894,15 +894,15 @@ function OutputStream(options) { def.print(output); }); var p = output.parent(); - var in_for = p instanceof AST_For || p instanceof AST_ForIn; + var in_for = p instanceof Cola.AST_For || p instanceof Cola.AST_ForIn; var avoid_semicolon = in_for && p.init === this; if (!avoid_semicolon) output.semicolon(); }); - DEFPRINT(AST_Var, function(self, output){ + DEFPRINT(Cola.AST_Var, function(self, output){ self._do_print(output, "var"); }); - DEFPRINT(AST_Const, function(self, output){ + DEFPRINT(Cola.AST_Const, function(self, output){ self._do_print(output, "const"); }); @@ -911,8 +911,8 @@ function OutputStream(options) { else try { // need to take some precautions here: // https://github.com/mishoo/UglifyJS2/issues/60 - node.walk(new TreeWalker(function(node){ - if (node instanceof AST_Binary && node.operator == "in") + node.walk(new Cola.TreeWalker(function(node){ + if (node instanceof Cola.AST_Binary && node.operator == "in") throw output; })); node.print(output); @@ -922,22 +922,22 @@ function OutputStream(options) { } }; - DEFPRINT(AST_VarDef, function(self, output){ + DEFPRINT(Cola.AST_VarDef, function(self, output){ self.name.print(output); if (self.value) { output.space(); output.print("="); output.space(); var p = output.parent(1); - var noin = p instanceof AST_For || p instanceof AST_ForIn; + var noin = p instanceof Cola.AST_For || p instanceof Cola.AST_ForIn; parenthesize_for_noin(self.value, output, noin); } }); /* -----[ other expressions ]----- */ - DEFPRINT(AST_Call, function(self, output){ + DEFPRINT(Cola.AST_Call, function(self, output){ self.expression.print(output); - if (self instanceof AST_New && no_constructor_parens(self, output)) + if (self instanceof Cola.AST_New && no_constructor_parens(self, output)) return; output.with_parens(function(){ self.args.forEach(function(expr, i){ @@ -946,13 +946,13 @@ function OutputStream(options) { }); }); }); - DEFPRINT(AST_New, function(self, output){ + DEFPRINT(Cola.AST_New, function(self, output){ output.print("new"); output.space(); - AST_Call.prototype._codegen(self, output); + Cola.AST_Call.prototype._codegen(self, output); }); - AST_Seq.DEFMETHOD("_do_print", function(output){ + Cola.AST_Seq.DEFMETHOD("_do_print", function(output){ this.car.print(output); if (this.cdr) { output.comma(); @@ -963,10 +963,10 @@ function OutputStream(options) { this.cdr.print(output); } }); - DEFPRINT(AST_Seq, function(self, output){ + DEFPRINT(Cola.AST_Seq, function(self, output){ self._do_print(output); // var p = output.parent(); - // if (p instanceof AST_Statement) { + // if (p instanceof Cola.AST_Statement) { // output.with_indent(output.next_indent(), function(){ // self._do_print(output); // }); @@ -974,10 +974,10 @@ function OutputStream(options) { // self._do_print(output); // } }); - DEFPRINT(AST_Dot, function(self, output){ + DEFPRINT(Cola.AST_Dot, function(self, output){ var expr = self.expression; expr.print(output); - if (expr instanceof AST_Number && expr.getValue() >= 0) { + if (expr instanceof Cola.AST_Number && expr.getValue() >= 0) { if (!/[xa-f.]/i.test(output.last())) { output.print("."); } @@ -987,31 +987,31 @@ function OutputStream(options) { output.add_mapping(self.end); output.print_name(self.property); }); - DEFPRINT(AST_Sub, function(self, output){ + DEFPRINT(Cola.AST_Sub, function(self, output){ self.expression.print(output); output.print("["); self.property.print(output); output.print("]"); }); - DEFPRINT(AST_UnaryPrefix, function(self, output){ + DEFPRINT(Cola.AST_UnaryPrefix, function(self, output){ var op = self.operator; output.print(op); if (/^[a-z]/i.test(op)) output.space(); self.expression.print(output); }); - DEFPRINT(AST_UnaryPostfix, function(self, output){ + DEFPRINT(Cola.AST_UnaryPostfix, function(self, output){ self.expression.print(output); output.print(self.operator); }); - DEFPRINT(AST_Binary, function(self, output){ + DEFPRINT(Cola.AST_Binary, function(self, output){ self.left.print(output); output.space(); output.print(self.operator); if (self.operator == "<" - && self.right instanceof AST_UnaryPrefix + && self.right instanceof Cola.AST_UnaryPrefix && self.right.operator == "!" - && self.right.expression instanceof AST_UnaryPrefix + && self.right.expression instanceof Cola.AST_UnaryPrefix && self.right.expression.operator == "--") { // space is mandatory to avoid outputting ") && S.newline_before) { - forward(3); - return skip_line_comment("comment4"); - } - } - ch = peek(); - if (!ch) return token("eof"); +Cola.tokenizer.prototype.read_num = function (prefix) { + var has_e = false, after_e = false, has_x = false, has_dot = prefix == "."; + var num = this.read_while(function(ch, i){ var code = ch.charCodeAt(0); switch (code) { - case 34: case 39: /* ColaScript */ case 96: return read_string(); - case 46: return handle_dot(); - case 47: return handle_slash(); + case 120: case 88: // xX + return has_x ? false : (has_x = true); + case 101: case 69: // eE + return has_x ? true : has_e ? false : (has_e = after_e = true); + case 45: // - + return after_e || (i == 0 && !prefix); + case 43: // + + return after_e; + case (after_e = false, 46): // . + return (!has_dot && !has_x && !has_e) ? (has_dot = true) : false; } - if (is_digit(code)) return read_num(); - if (PUNC_CHARS(ch)){ - if (S.string.at[S.string.level].inside && (S.string.at[S.string.level].inside_at || S.string.at[S.string.level].inside_braces)) { - if (ch == '{') S.string.at[S.string.level].balance++; - else if (ch == '}') S.string.at[S.string.level].balance--; + return Cola.is_alphanumeric_char(code); + }); + if (prefix) num = prefix + num; + var valid = Cola.parse_js_number(num); + if (!isNaN(valid)) { + return this.token("num", valid); + } else { + this.parse_error("Invalid syntax: " + num); + } +}; - if (S.string.at[S.string.level].balance == 0) - if (S.string.at[S.string.level].inside_at) S.string.at[S.string.level].inside_at = false; - else { - S.string.at[S.string.level].inside_braces = false; - return next(), next(), token("punc", "}}"); - } +Cola.tokenizer.prototype.read_escaped_char = function (in_string) { + var ch = this.next(true, in_string); + switch (ch.charCodeAt(0)) { + case 110 : return "\n"; + case 114 : return "\r"; + case 116 : return "\t"; + case 98 : return "\b"; + case 118 : return "\u000b"; // \v + case 102 : return "\f"; + case 48 : return "\0"; + case 120 : return String.fromCharCode(this.hex_bytes(2)); // \x + case 117 : return String.fromCharCode(this.hex_bytes(4)); // \u + case 10 : return ""; // newline + default : return ch; + } +}; + +Cola.tokenizer.prototype.hex_bytes = function (n) { + var num = 0; + for (; n > 0; --n) { + var digit = parseInt(this.next(true), 16); + if (isNaN(digit)) + this.parse_error("Invalid hex-character pattern in string"); + num = (num << 4) | digit; + } + return num; +}; + +Cola.tokenizer.prototype.read_string = Cola.tokenizer.with_eof_error("Unterminated string constant", function(raw){ + var quote = this.next(), ret = ""; + + if (!raw) { + if (this.S.string.at[this.S.string.level].inside && (this.S.string.at[this.S.string.level].inside_at || this.S.string.at[this.S.string.level].inside_braces)) { + this.S.string.level++; + this.S.string.at[this.S.string.level] = new Cola.tokenizer.StringInfo(); + } + this.S.string.at[this.S.string.level].inside = true; + + if (quote != '"' && quote != "'" && quote != '`') { + ret = quote; + quote = this.S.string.at[this.S.string.level].quote; + } else + + if (quote == this.S.string.at[this.S.string.level].quote){ + this.S.string.at[this.S.string.level].inside = false; + this.S.string.at[this.S.string.level].quote = ''; + if(this.S.string.level != 0){ + delete this.S.string.at[this.S.string.level]; + this.S.string.level--; } + return this.next_token(); + } else - return token("punc", next()); + this.S.string.at[this.S.string.level].quote = quote; + if (this.peek() == '@' || this.peek() == '{' && this.peek(1) == '{') return this.token("string", ""); + } + + for (;;) { + var ch = this.next(true); + if (!raw && ch == "\\") { + // read OctalEscapeSequence (XXX: deprecated if "strict mode") + // https://github.com/mishoo/UglifyJS/issues/178 + var octal_len = 0, first = null; + ch = this.read_while(function(ch){ + if (ch >= "0" && ch <= "7") { + if (!first) { + first = ch; + return ++octal_len; + } + else if (first <= "3" && octal_len <= 2) return ++octal_len; + else if (first >= "4" && octal_len <= 1) return ++octal_len; + } + return false; + }); + if (octal_len > 0) ch = String.fromCharCode(parseInt(ch, 8)); + else ch = this.read_escaped_char(true); } - if (ch == '@') return read_at(); - if (OPERATOR_CHARS(ch)) return read_operator(); - if (ch == 'r' && (peek(1) == '"' || peek(1) == "'" || peek(1) == '`')) return next(), read_string(true); - if (code == 92 || is_identifier_start(code)) return read_word(); - parse_error("Unexpected character '" + ch + "'"); + else if (ch == quote) { + if(!raw){ + this.S.string.at[this.S.string.level].inside = false; + this.S.string.at[this.S.string.level].quote = ''; + if(this.S.string.level != 0){ + delete this.S.string.at[this.S.string.level]; + this.S.string.level--; + } + } + break; + } + ret += ch; + if (!raw && (this.peek() == '@' || this.peek() == '{' && this.peek(1) == '{')) break; + } + + return this.token("string", ret); +}); + +Cola.tokenizer.prototype.read_at = function (){ + var at = this.next(); + + if (this.S.string.at[this.S.string.level].inside && Cola.is_identifier_char(this.peek())) { + this.S.string.at[this.S.string.level].after_at = true; + return this.token("punc", "@"); + } else + + if (this.S.string.at[this.S.string.level].inside && this.peek() == '{') { + this.S.string.at[this.S.string.level].inside_at = true; + this.S.string.at[this.S.string.level].balance = 1; + return this.token("punc", "@" + this.next()); + } + + this.parse_error('Unexpected character "@"'); +} + +Cola.tokenizer.prototype.read_braces = function (){ + this.next(), this.next(); + this.S.string.at[this.S.string.level].inside_braces = true; + this.S.string.at[this.S.string.level].balance = 1; + return this.token("punc", "{{"); +} + +Cola.tokenizer.prototype.skip_line_comment = function (type) { + var regex_allowed = this.S.regex_allowed; + var i = this.find("\n"), ret; + if (i == -1) { + ret = this.S.text.substr(this.S.pos); + this.S.pos = this.S.text.length; + } else { + ret = this.S.text.substring(this.S.pos, i); + this.S.pos = i; + } + this.S.comments_before.push(this.token(type, ret, true)); + this.S.regex_allowed = regex_allowed; + return this.next_token(); +}; + +Cola.tokenizer.prototype.skip_multiline_comment = Cola.tokenizer.with_eof_error("Unterminated multiline comment", function(){ + var regex_allowed = this.S.regex_allowed; + var i = this.find("*/", true); + var text = this.S.text.substring(this.S.pos, i); + var a = text.split("\n"), n = a.length; + // update stream position + this.S.pos = i + 2; + this.S.line += n - 1; + if (n > 1) this.S.col = a[n - 1].length; + else this.S.col += a[n - 1].length; + this.S.col += 2; + var nlb = this.S.newline_before = this.S.newline_before || text.indexOf("\n") >= 0; + this.S.comments_before.push(this.token("comment2", text, true)); + this.S.regex_allowed = regex_allowed; + this.S.newline_before = nlb; + return this.next_token(); +}); + +Cola.tokenizer.prototype.read_name = function () { + var backslash = false, name = "", ch, escaped = false, hex; + while ((ch = this.peek()) != null) { + if (!backslash) { + if (ch == "\\") escaped = backslash = true, this.next(); + else if (Cola.is_identifier_char(ch)) name += this.next(); + else break; + } + else { + if (ch != "u") this.parse_error("Expecting UnicodeEscapeSequence -- uXXXX"); + ch = this.read_escaped_char(); + if (!Cola.is_identifier_char(ch)) this.parse_error("Unicode char: " + ch.charCodeAt(0) + " is not valid in identifier"); + name += ch; + backslash = false; + } + } + if (Cola.KEYWORDS(name) && escaped) { + hex = name.charCodeAt(0).toString(16).toUpperCase(); + name = "\\u" + "0000".substr(hex.length) + hex + name.slice(1); + } + if (this.S.string.at[this.S.string.level].inside && this.S.string.at[this.S.string.level].after_at) this.S.string.at[this.S.string.level].after_at = false; + return name; +}; + +Cola.tokenizer.prototype.read_regexp = Cola.tokenizer.with_eof_error("Unterminated regular expression", function(regexp){ + var prev_backslash = false, ch, in_class = false; + while ((ch = this.next(true))) if (prev_backslash) { + regexp += "\\" + ch; + prev_backslash = false; + } else if (ch == "[") { + in_class = true; + regexp += ch; + } else if (ch == "]" && in_class) { + in_class = false; + regexp += ch; + } else if (ch == "/" && !in_class) { + break; + } else if (ch == "\\") { + prev_backslash = true; + } else { + regexp += ch; + } + var mods = this.read_name(); + return this.token("regexp", /* new RegExp(regexp, mods) ColaScript */ "/" + regexp + "/" + mods); +}); + +Cola.tokenizer.prototype.read_operator = function (prefix) { + function grow(op) { + if (!this.peek()) return op; + var bigger = op + this.peek(); + if (Cola.OPERATORS(bigger)) { + this.next(); + return grow(bigger); + } else { + return op; + } + }; + return this.token("operator", grow(prefix || this.next())); +}; + +Cola.tokenizer.prototype.handle_slash = function () { + this.next(); + switch (this.peek()) { + case "/": + this.next(); + return this.skip_line_comment("comment1"); + case "*": + this.next(); + return this.skip_multiline_comment(); + } + return this.S.regex_allowed ? this.read_regexp("") : this.read_operator("/"); +}; + +Cola.tokenizer.prototype.handle_dot = function () { + this.next(); + return Cola.is_digit(this.peek().charCodeAt(0)) + ? this.read_num(".") + : this.token("punc", "."); }; - next_token.context = function(nc) { - if (nc) S = nc; - return S; +Cola.tokenizer.prototype.read_word = function () { + var word = this.read_name(); + if (this.prev_was_dot) return this.token("name", word); + return Cola.KEYWORDS_ATOM(word) ? this.token("atom", word) + : !Cola.KEYWORDS(word) ? this.token("name", word) + : Cola.OPERATORS(word) ? this.token("operator", word) + : this.token("keyword", word); }; - return next_token; +Cola.tokenizer.prototype.next_token = function (force_regexp) { + if (force_regexp != null) + return this.read_regexp(force_regexp); + var ch; + if (this.S.string.at[this.S.string.level].inside && !this.S.string.at[this.S.string.level].after_at && !this.S.string.at[this.S.string.level].inside_at && !this.S.string.at[this.S.string.level].inside_braces) { + ch = this.peek(); + if (ch == '@') return this.read_at(); + if (ch == '{' && this.peek(1) == '{') return this.read_braces(); + return this.read_string(); + } + + this.skip_whitespace(); + this.start_token(); + if (this.html5_comments) { + if (this.looking_at("") && this.S.newline_before) { + this.forward(3); + return this.skip_line_comment("comment4"); + } + } + ch = this.peek(); + if (!ch) return this.token("eof"); + var code = ch.charCodeAt(0); + switch (code) { + case 34: case 39: /* ColaScript */ case 96: return this.read_string(); + case 46: return this.handle_dot(); + case 47: return this.handle_slash(); + } + if (Cola.is_digit(code)) return this.read_num(); + if (Cola.PUNC_CHARS(ch)){ + if (this.S.string.at[this.S.string.level].inside && (this.S.string.at[this.S.string.level].inside_at || this.S.string.at[this.S.string.level].inside_braces)) { + if (ch == '{') this.S.string.at[this.S.string.level].balance++; + else if (ch == '}') this.S.string.at[this.S.string.level].balance--; + + if (this.S.string.at[this.S.string.level].balance == 0) + if (this.S.string.at[this.S.string.level].inside_at) this.S.string.at[this.S.string.level].inside_at = false; + else { + this.S.string.at[this.S.string.level].inside_braces = false; + return this.next(), this.next(), this.token("punc", "}}"); + } + } + + return this.token("punc", this.next()); + } + if (ch == '@') return this.read_at(); + if (Cola.OPERATOR_CHARS(ch)) return this.read_operator(); + if (ch == 'r' && (this.peek(1) == '"' || this.peek(1) == "'" || this.peek(1) == '`')) return this.next(), this.read_string(true); + if (code == 92 || Cola.is_identifier_start(code)) return this.read_word(); + this.parse_error("Unexpected character '" + ch + "'"); +}; + +Cola.tokenizer.prototype.next_token.context = function(nc) { + if (nc) this.S = nc; + return this.S; }; /* -----[ Parser (constants) ]----- */ -var UNARY_PREFIX = makePredicate([ +Cola.UNARY_PREFIX = Cola.makePredicate([ + "typeof", + "void", + "delete", + "--", + "++", + "!", + "~", + "-", + "+" +]); +Cola.cUNARY_PREFIX = Cola.makePredicate([ "typeof", - //"void", ColaScript "delete", "--", "++", @@ -692,11 +715,12 @@ var UNARY_PREFIX = makePredicate([ "+" ]); -var UNARY_POSTFIX = makePredicate([ "--", "++" ]); +Cola.UNARY_POSTFIX = Cola.makePredicate([ "--", "++" ]); -var ASSIGNMENT = makePredicate([ "=", "+=", "-=", "/=", "*=", "%=", ">>=", "<<=", ">>>=", "|=", "^=", "&="/* ColaScript */, "?=" ]); +Cola.ASSIGNMENT = Cola.makePredicate([ "=", "+=", "-=", "/=", "*=", "%=", ">>=", "<<=", ">>>=", "|=", "^=", "&=" ]); +Cola.cASSIGNMENT = Cola.makePredicate([ "=", "+=", "-=", "/=", "*=", "%=", ">>=", "<<=", ">>>=", "|=", "^=", "&="/* ColaScript */, "?=" ]); -var PRECEDENCE = (function(a, ret){ +Cola.mergeTokens = function (a, ret) { for (var i = 0; i < a.length; ++i) { var b = a[i]; for (var j = 0; j < b.length; ++j) { @@ -704,7 +728,24 @@ var PRECEDENCE = (function(a, ret){ } } return ret; -})( +}; + +Cola.PRECEDENCE = Cola.mergeTokens( + [ + ["||"], + ["&&"], + ["|"], + ["^"], + ["&"], + ["==", "===", "!=", "!=="], + ["<", ">", "<=", ">=", "in", "instanceof"], + [">>", "<<", ">>>"], + ["+", "-"], + ["*", "/", "%"] + ], + {} +); +Cola.cPRECEDENCE = Cola.mergeTokens( [ ["||"], ["&&"], @@ -716,21 +757,20 @@ var PRECEDENCE = (function(a, ret){ [">>", "<<", ">>>"], ["+", "-"], ["*", "/", "%"], - // ColaScript ["is", "isnt", "**", "%%"] ], {} ); -var STATEMENTS_WITH_LABELS = array_to_hash([ "for", "do", "while", "switch" ]); +Cola.STATEMENTS_WITH_LABELS = Cola.array_to_hash([ "for", "do", "while", "switch" ]); -var ATOMIC_START_TOKEN = array_to_hash([ "atom", "num", "string", "regexp", "name" ]); +Cola.ATOMIC_START_TOKEN = Cola.array_to_hash([ "atom", "num", "string", "regexp", "name" ]); /* -----[ Parser ]----- */ -function parse($TEXT, options) { +Cola.parse = function ($TEXT, options) { - options = defaults(options, { + options = Cola.defaults(options, { strict : false, filename : null, toplevel : null, @@ -738,8 +778,10 @@ function parse($TEXT, options) { html5_comments : true }); + var tzr = typeof $TEXT == "string" ? new Cola.tokenizer($TEXT, options.filename, options.html5_comments) : $TEXT; + var S = { - input : (typeof $TEXT == "string" ? tokenizer($TEXT, options.filename, options.html5_comments) : $TEXT), + input : function(){ return tzr.next_token() }, token : null, prev : null, peeked : null, @@ -752,7 +794,7 @@ function parse($TEXT, options) { S.token = next(); function is(type, value) { - return is_token(S.token, type, value); + return Cola.is_token(S.token, type, value); }; function peek() { return S.peeked || (S.peeked = S.input()); }; @@ -777,7 +819,7 @@ function parse($TEXT, options) { function croak(msg, line, col, pos) { var ctx = S.input.context(); - js_error(msg, + Cola.js_error(msg, ctx.filename, line != null ? line : ctx.tokline, col != null ? col : ctx.tokcol, @@ -847,8 +889,8 @@ function parse($TEXT, options) { case "string": var dir = S.in_directives, stat = simple_statement(); // XXXv2: decide how to fix directives - if (dir && stat.body instanceof AST_String && !is("punc", ",")) - return new AST_Directive({ value: stat.body.value }); + if (dir && stat.body instanceof Cola.AST_String && !is("punc", ",")) + return new Cola.AST_Directive({ value: stat.body.value }); return stat; case "num": case "regexp": @@ -857,14 +899,14 @@ function parse($TEXT, options) { return simple_statement(); case "name": - return is_token(peek(), "punc", ":") + return Cola.is_token(peek(), "punc", ":") ? labeled_statement() : simple_statement(); case "punc": switch (S.token.value) { case "{": - return new AST_BlockStatement({ + return new Cola.AST_BlockStatement({ start : S.token, body : block_(), end : prev() @@ -874,7 +916,7 @@ function parse($TEXT, options) { return simple_statement(); case ";": next(); - return new AST_EmptyStatement(); + return new Cola.AST_EmptyStatement(); default: unexpected(); } @@ -882,23 +924,23 @@ function parse($TEXT, options) { case "keyword": switch (tmp = S.token.value, next(), tmp) { case "break": - return break_cont(AST_Break); + return break_cont(Cola.AST_Break); case "continue": - return break_cont(AST_Continue); + return break_cont(Cola.AST_Continue); case "debugger": semicolon(); - return new AST_Debugger(); + return new Cola.AST_Debugger(); case "do": - return new AST_Do({ + return new Cola.AST_Do({ body : in_loop(statement), condition : (expect_token("keyword", "while"), tmp = parenthesised(), semicolon(), tmp) }); case "while": - return new AST_While({ + return new Cola.AST_While({ condition : parenthesised(), body : in_loop(statement) }); @@ -907,7 +949,7 @@ function parse($TEXT, options) { return for_(); case "function": - return function_(AST_Defun); + return function_(Cola.AST_Defun); case "if": return if_(); @@ -915,7 +957,7 @@ function parse($TEXT, options) { case "return": if (S.in_function == 0) croak("'return' outside of function"); - return new AST_Return({ + return new Cola.AST_Return({ value: ( is("punc", ";") ? (next(), null) : can_insert_semicolon() @@ -924,7 +966,7 @@ function parse($TEXT, options) { }); case "switch": - return new AST_Switch({ + return new Cola.AST_Switch({ expression : parenthesised(), body : in_loop(switch_body_) }); @@ -932,7 +974,7 @@ function parse($TEXT, options) { case "throw": if (S.token.nlb) croak("Illegal newline after 'throw'"); - return new AST_Throw({ + return new Cola.AST_Throw({ value: (tmp = expression(true), semicolon(), tmp) }); @@ -946,7 +988,7 @@ function parse($TEXT, options) { return tmp = const_(), semicolon(), tmp; case "with": - return new AST_With({ + return new Cola.AST_With({ expression : parenthesised(), body : statement() }); @@ -958,8 +1000,8 @@ function parse($TEXT, options) { }); function labeled_statement() { - var label = as_symbol(AST_Label); - if (find_if(function(l){ return l.name == label.name }, S.labels)) { + var label = as_symbol(Cola.AST_Label); + if (Cola.find_if(function(l){ return l.name == label.name }, S.labels)) { // ECMA-262, 12.12: An ECMAScript program is considered // syntactically incorrect if it contains a // LabelledStatement that is enclosed by a @@ -970,32 +1012,32 @@ function parse($TEXT, options) { S.labels.push(label); var stat = statement(); S.labels.pop(); - if (!(stat instanceof AST_IterationStatement)) { + if (!(stat instanceof Cola.AST_IterationStatement)) { // check for `continue` that refers to this label. // those should be reported as syntax errors. // https://github.com/mishoo/UglifyJS2/issues/287 label.references.forEach(function(ref){ - if (ref instanceof AST_Continue) { + if (ref instanceof Cola.AST_Continue) { ref = ref.label.start; croak("Continue label `" + label.name + "` refers to non-IterationStatement.", ref.line, ref.col, ref.pos); } }); } - return new AST_LabeledStatement({ body: stat, label: label }); + return new Cola.AST_LabeledStatement({ body: stat, label: label }); }; function simple_statement(tmp) { - return new AST_SimpleStatement({ body: (tmp = expression(true), semicolon(), tmp) }); + return new Cola.AST_SimpleStatement({ body: (tmp = expression(true), semicolon(), tmp) }); }; function break_cont(type) { var label = null, ldef; if (!can_insert_semicolon()) { - label = as_symbol(AST_LabelRef, true); + label = as_symbol(Cola.AST_LabelRef, true); } if (label != null) { - ldef = find_if(function(l){ return l.name == label.name }, S.labels); + ldef = Cola.find_if(function(l){ return l.name == label.name }, S.labels); if (!ldef) croak("Undefined label " + label.name); label.thedef = ldef; @@ -1016,7 +1058,7 @@ function parse($TEXT, options) { ? (next(), var_(true)) : expression(true, true); if (is("operator", "in")) { - if (init instanceof AST_Var && init.definitions.length > 1) + if (init instanceof Cola.AST_Var && init.definitions.length > 1) croak("Only one variable declaration allowed in for..in loop"); next(); return for_in(init); @@ -1031,7 +1073,7 @@ function parse($TEXT, options) { expect(";"); var step = is("punc", ")") ? null : expression(true); expect(")"); - return new AST_For({ + return new Cola.AST_For({ init : init, condition : test, step : step, @@ -1040,10 +1082,10 @@ function parse($TEXT, options) { }; function for_in(init) { - var lhs = init instanceof AST_Var ? init.definitions[0].name : null; + var lhs = init instanceof Cola.AST_Var ? init.definitions[0].name : null; var obj = expression(true); expect(")"); - return new AST_ForIn({ + return new Cola.AST_ForIn({ init : init, name : lhs, object : obj, @@ -1052,8 +1094,8 @@ function parse($TEXT, options) { }; var function_ = function(ctor) { - var in_statement = ctor === AST_Defun; - var name = is("name") ? as_symbol(in_statement ? AST_SymbolDefun : AST_SymbolLambda) : null; + var in_statement = ctor === Cola.AST_Defun; + var name = is("name") ? as_symbol(in_statement ? Cola.AST_SymbolDefun : Cola.AST_SymbolLambda) : null; if (in_statement && !name) unexpected(); expect("("); @@ -1062,7 +1104,7 @@ function parse($TEXT, options) { argnames: (function(first, a){ while (!is("punc", ")")) { if (first) first = false; else expect(","); - a.push(as_symbol(AST_SymbolFunarg)); + a.push(as_symbol(Cola.AST_SymbolFunarg)); } next(); return a; @@ -1087,7 +1129,7 @@ function parse($TEXT, options) { next(); belse = statement(); } - return new AST_If({ + return new Cola.AST_If({ condition : cond, body : body, alternative : belse @@ -1113,7 +1155,7 @@ function parse($TEXT, options) { if (is("keyword", "case")) { if (branch) branch.end = prev(); cur = []; - branch = new AST_Case({ + branch = new Cola.AST_Case({ start : (tmp = S.token, next(), tmp), expression : expression(true), body : cur @@ -1124,7 +1166,7 @@ function parse($TEXT, options) { else if (is("keyword", "default")) { if (branch) branch.end = prev(); cur = []; - branch = new AST_Default({ + branch = new Cola.AST_Default({ start : (tmp = S.token, next(), expect(":"), tmp), body : cur }); @@ -1146,9 +1188,9 @@ function parse($TEXT, options) { var start = S.token; next(); expect("("); - var name = as_symbol(AST_SymbolCatch); + var name = as_symbol(Cola.AST_SymbolCatch); expect(")"); - bcatch = new AST_Catch({ + bcatch = new Cola.AST_Catch({ start : start, argname : name, body : block_(), @@ -1158,7 +1200,7 @@ function parse($TEXT, options) { if (is("keyword", "finally")) { var start = S.token; next(); - bfinally = new AST_Finally({ + bfinally = new Cola.AST_Finally({ start : start, body : block_(), end : prev() @@ -1166,7 +1208,7 @@ function parse($TEXT, options) { } if (!bcatch && !bfinally) croak("Missing catch/finally blocks"); - return new AST_Try({ + return new Cola.AST_Try({ body : body, bcatch : bcatch, bfinally : bfinally @@ -1176,9 +1218,9 @@ function parse($TEXT, options) { function vardefs(no_in, in_const) { var a = []; for (;;) { - a.push(new AST_VarDef({ + a.push(new Cola.AST_VarDef({ start : S.token, - name : as_symbol(in_const ? AST_SymbolConst : AST_SymbolVar), + name : as_symbol(in_const ? Cola.AST_SymbolConst : Cola.AST_SymbolVar), value : is("operator", "=") ? (next(), expression(false, no_in)) : null, end : prev() })); @@ -1190,7 +1232,7 @@ function parse($TEXT, options) { }; var var_ = function(no_in) { - return new AST_Var({ + return new Cola.AST_Var({ start : prev(), definitions : vardefs(no_in, false), end : prev() @@ -1198,7 +1240,7 @@ function parse($TEXT, options) { }; var const_ = function() { - return new AST_Const({ + return new Cola.AST_Const({ start : prev(), definitions : vardefs(false, true), end : prev() @@ -1215,7 +1257,7 @@ function parse($TEXT, options) { } else { args = []; } - return subscripts(new AST_New({ + return subscripts(new Cola.AST_New({ start : start, expression : newexp, args : args, @@ -1224,19 +1266,19 @@ function parse($TEXT, options) { }; function string_template_(start_token) { - var body = [new AST_String({ start: start_token, end: start_token, value: start_token.value })]; + var body = [new Cola.AST_String({ start: start_token, end: start_token, value: start_token.value })]; next(); //if (!is('punc', '@') && !is('punc', '@{')) return body[0]; while (is('punc', '@') || is('punc', '@{') || is('punc', '{{') || is('string', null)) if (is('string', null)) { - body.push(new AST_String({ start: S.token, end: S.token, value: S.token.value })); + body.push(new Cola.AST_String({ start: S.token, end: S.token, value: S.token.value })); next(); } else if (is('punc', '@')) { next(); - body.push(_make_symbol(AST_SymbolRef)); + body.push(_make_symbol(Cola.AST_SymbolRef)); next(); } else @@ -1254,11 +1296,11 @@ function parse($TEXT, options) { var last = body[body.length - 1]; body[0].value = body[0].value.replace(/^[ \t]*[\n\r]/,''); - if (last instanceof AST_String) { + if (last instanceof Cola.AST_String) { var offstr = last.value.match(/[\n\r][ \t]*$/); if(offstr){ offstr = offstr[0]; - for(var i in body) if(body[i] instanceof AST_String){ + for(var i in body) if(body[i] instanceof Cola.AST_String){ body[i].value = body[i].value.replace(new RegExp(offstr, 'g'), '\n'); body[i].value = body[i].value.replace(/\n/g, '\n'); } @@ -1267,7 +1309,7 @@ function parse($TEXT, options) { } if (body.length == 1) return body[0]; - return new AST_StringTemplate({ + return new Cola.AST_StringTemplate({ start : start_token, end : prev(), body : body @@ -1279,27 +1321,27 @@ function parse($TEXT, options) { switch (tok.type) { case "name": case "keyword": - ret = _make_symbol(AST_SymbolRef); + ret = _make_symbol(Cola.AST_SymbolRef); break; case "num": - ret = new AST_Number({ start: tok, end: tok, value: tok.value }); + ret = new Cola.AST_Number({ start: tok, end: tok, value: tok.value }); break; case "string": - return string_template_(tok);//new AST_String({ start: tok, end: tok, value: tok.value }); + return string_template_(tok);//new Cola.AST_String({ start: tok, end: tok, value: tok.value }); //break; case "regexp": - ret = new AST_RegExp({ start: tok, end: tok, value: tok.value }); + ret = new Cola.AST_RegExp({ start: tok, end: tok, value: tok.value }); break; case "atom": switch (tok.value) { case "false": /* ColaScript */ case "off": case "no": - ret = new AST_False({ start: tok, end: tok }); + ret = new Cola.AST_False({ start: tok, end: tok }); break; case "true": /* ColaScript */ case "on": case "yes": - ret = new AST_True({ start: tok, end: tok }); + ret = new Cola.AST_True({ start: tok, end: tok }); break; case "null": - ret = new AST_Null({ start: tok, end: tok }); + ret = new Cola.AST_Null({ start: tok, end: tok }); break; } break; @@ -1331,12 +1373,12 @@ function parse($TEXT, options) { } if (is("keyword", "function")) { next(); - var func = function_(AST_Function); + var func = function_(Cola.AST_Function); func.start = start; func.end = prev(); return subscripts(func, allow_calls); } - if (ATOMIC_START_TOKEN[S.token.type]) { + if (Cola.ATOMIC_START_TOKEN[S.token.type]) { return subscripts(as_atom_node(), allow_calls); } unexpected(); @@ -1348,7 +1390,7 @@ function parse($TEXT, options) { if (first) first = false; else expect(","); if (allow_trailing_comma && is("punc", closing)) break; if (is("punc", ",") && allow_empty) { - a.push(new AST_Hole({ start: S.token, end: S.token })); + a.push(new Cola.AST_Hole({ start: S.token, end: S.token })); } else { a.push(expression(false)); } @@ -1359,7 +1401,7 @@ function parse($TEXT, options) { var array_ = embed_tokens(function() { expect("["); - return new AST_Array({ + return new Cola.AST_Array({ elements: expr_list("]", !options.strict, true) }); }); @@ -1377,26 +1419,26 @@ function parse($TEXT, options) { var name = as_property_name(); if (type == "name" && !is("punc", ":")) { if (name == "get") { - a.push(new AST_ObjectGetter({ + a.push(new Cola.AST_ObjectGetter({ start : start, key : as_atom_node(), - value : function_(AST_Accessor), + value : function_(Cola.AST_Accessor), end : prev() })); continue; } if (name == "set") { - a.push(new AST_ObjectSetter({ + a.push(new Cola.AST_ObjectSetter({ start : start, key : as_atom_node(), - value : function_(AST_Accessor), + value : function_(Cola.AST_Accessor), end : prev() })); continue; } } expect(":"); - a.push(new AST_ObjectKeyVal({ + a.push(new Cola.AST_ObjectKeyVal({ start : start, key : name, value : expression(false), @@ -1404,7 +1446,7 @@ function parse($TEXT, options) { })); } next(); - return new AST_Object({ properties: a }); + return new Cola.AST_Object({ properties: a }); }); function as_property_name() { @@ -1439,7 +1481,7 @@ function parse($TEXT, options) { function _make_symbol(type) { var name = S.token.value; - return new (name == "this" ? AST_This : type)({ + return new (name == "this" ? Cola.AST_This : type)({ name : String(name), start : S.token, end : S.token @@ -1460,7 +1502,7 @@ function parse($TEXT, options) { var start = expr.start; if (is("punc", ".")) { next(); - return subscripts(new AST_Dot({ + return subscripts(new Cola.AST_Dot({ start : start, expression : expr, property : as_name(), @@ -1471,7 +1513,7 @@ function parse($TEXT, options) { next(); var prop = expression(true); expect("]"); - return subscripts(new AST_Sub({ + return subscripts(new Cola.AST_Sub({ start : start, expression : expr, property : prop, @@ -1480,7 +1522,7 @@ function parse($TEXT, options) { } if (allow_calls && is("punc", "(")) { next(); - return subscripts(new AST_Call({ + return subscripts(new Cola.AST_Call({ start : start, expression : expr, args : expr_list(")"), @@ -1492,17 +1534,17 @@ function parse($TEXT, options) { var maybe_unary = function(allow_calls) { var start = S.token; - if (is("operator") && UNARY_PREFIX(start.value)) { + if (is("operator") && Cola.UNARY_PREFIX(start.value)) { next(); handle_regexp(); - var ex = make_unary(AST_UnaryPrefix, start.value, maybe_unary(allow_calls)); + var ex = make_unary(Cola.AST_UnaryPrefix, start.value, maybe_unary(allow_calls)); ex.start = start; ex.end = prev(); return ex; } var val = expr_atom(allow_calls); - while (is("operator") && UNARY_POSTFIX(S.token.value) && !S.token.nlb) { - val = make_unary(AST_UnaryPostfix, S.token.value, val); + while (is("operator") && Cola.UNARY_POSTFIX(S.token.value) && !S.token.nlb) { + val = make_unary(Cola.AST_UnaryPostfix, S.token.value, val); val.start = start; val.end = S.token; next(); @@ -1519,11 +1561,11 @@ function parse($TEXT, options) { var expr_op = function(left, min_prec, no_in) { var op = is("operator") ? S.token.value : null; if (op == "in" && no_in) op = null; - var prec = op != null ? PRECEDENCE[op] : null; + var prec = op != null ? Cola.PRECEDENCE[op] : null; if (prec != null && prec > min_prec) { next(); var right = expr_op(maybe_unary(true), prec, no_in); - return expr_op(new AST_Binary({ + return expr_op(new Cola.AST_Binary({ start : left.start, left : left, operator : op, @@ -1545,7 +1587,7 @@ function parse($TEXT, options) { next(); var yes = expression(false); expect(":"); - return new AST_Conditional({ + return new Cola.AST_Conditional({ start : start, condition : expr, consequent : yes, @@ -1558,17 +1600,17 @@ function parse($TEXT, options) { function is_assignable(expr) { if (!options.strict) return true; - if (expr instanceof AST_This) return false; - return (expr instanceof AST_PropAccess || expr instanceof AST_Symbol); + if (expr instanceof Cola.AST_This) return false; + return (expr instanceof Cola.AST_PropAccess || expr instanceof Cola.AST_Symbol); }; var maybe_assign = function(no_in) { var start = S.token; var left = maybe_conditional(no_in), val = S.token.value; - if (is("operator") && ASSIGNMENT(val)) { + if (is("operator") && Cola.ASSIGNMENT(val)) { if (is_assignable(left)) { next(); - return new AST_Assign({ + return new Cola.AST_Assign({ start : start, left : left, operator : val, @@ -1586,7 +1628,7 @@ function parse($TEXT, options) { var expr = maybe_assign(no_in); if (commas && is("punc", ",")) { next(); - return new AST_Seq({ + return new Cola.AST_Seq({ start : start, car : expr, cdr : expression(true, no_in), @@ -1618,7 +1660,7 @@ function parse($TEXT, options) { toplevel.body = toplevel.body.concat(body); toplevel.end = end; } else { - toplevel = new AST_Toplevel({ start: start, body: body, end: end }); + toplevel = new Cola.AST_Toplevel({ start: start, body: body, end: end }); } return toplevel; })(); diff --git a/lib/scope.js b/lib/scope.js index 1ce17fa6..6d09fb0d 100644 --- a/lib/scope.js +++ b/lib/scope.js @@ -64,15 +64,15 @@ SymbolDef.prototype = { mangle: function(options) { if (!this.mangled_name && !this.unmangleable(options)) { var s = this.scope; - if (!options.screw_ie8 && this.orig[0] instanceof AST_SymbolLambda) + if (!options.screw_ie8 && this.orig[0] instanceof Cola.AST_SymbolLambda) s = s.parent_scope; this.mangled_name = s.next_mangled(options, this); } } }; -AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){ - options = defaults(options, { +Cola.AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){ + options = Cola.defaults(options, { screw_ie8: false }); @@ -81,17 +81,17 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){ var scope = self.parent_scope = null; var defun = null; var nesting = 0; - var tw = new TreeWalker(function(node, descend){ - if (options.screw_ie8 && node instanceof AST_Catch) { + var tw = new Cola.TreeWalker(function(node, descend){ + if (options.screw_ie8 && node instanceof Cola.AST_Catch) { var save_scope = scope; - scope = new AST_Scope(node); + scope = new Cola.AST_Scope(node); scope.init_scope_vars(nesting); scope.parent_scope = save_scope; descend(); scope = save_scope; return true; } - if (node instanceof AST_Scope) { + if (node instanceof Cola.AST_Scope) { node.init_scope_vars(nesting); var save_scope = node.parent_scope = scope; var save_defun = defun; @@ -99,39 +99,39 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){ ++nesting; descend(); --nesting; scope = save_scope; defun = save_defun; - return true; // don't descend again in TreeWalker + return true; // don't descend again in Cola.TreeWalker } - if (node instanceof AST_Directive) { + if (node instanceof Cola.AST_Directive) { node.scope = scope; - push_uniq(scope.directives, node.value); + Cola.push_uniq(scope.directives, node.value); return true; } - if (node instanceof AST_With) { + if (node instanceof Cola.AST_With) { for (var s = scope; s; s = s.parent_scope) s.uses_with = true; return; } - if (node instanceof AST_Symbol) { + if (node instanceof Cola.AST_Symbol) { node.scope = scope; } - if (node instanceof AST_SymbolLambda) { + if (node instanceof Cola.AST_SymbolLambda) { defun.def_function(node); } - else if (node instanceof AST_SymbolDefun) { + else if (node instanceof Cola.AST_SymbolDefun) { // Careful here, the scope where this should be defined is // the parent scope. The reason is that we enter a new - // scope when we encounter the AST_Defun node (which is - // instanceof AST_Scope) but we get to the symbol a bit + // scope when we encounter the Cola.AST_Defun node (which is + // instanceof Cola.AST_Scope) but we get to the symbol a bit // later. (node.scope = defun.parent_scope).def_function(node); } - else if (node instanceof AST_SymbolVar - || node instanceof AST_SymbolConst) { + else if (node instanceof Cola.AST_SymbolVar + || node instanceof Cola.AST_SymbolConst) { var def = defun.def_variable(node); - def.constant = node instanceof AST_SymbolConst; + def.constant = node instanceof Cola.AST_SymbolConst; def.init = tw.parent().value; } - else if (node instanceof AST_SymbolCatch) { + else if (node instanceof Cola.AST_SymbolCatch) { (options.screw_ie8 ? scope : defun) .def_variable(node); } @@ -140,16 +140,16 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){ // pass 2: find back references and eval var func = null; - var globals = self.globals = new Dictionary(); - var tw = new TreeWalker(function(node, descend){ - if (node instanceof AST_Lambda) { + var globals = self.globals = new Cola.Dictionary(); + var tw = new Cola.TreeWalker(function(node, descend){ + if (node instanceof Cola.AST_Lambda) { var prev_func = func; func = node; descend(); func = prev_func; return true; } - if (node instanceof AST_SymbolRef) { + if (node instanceof Cola.AST_SymbolRef) { var name = node.name; var sym = node.scope.find_variable(name); if (!sym) { @@ -163,7 +163,7 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){ globals.set(name, g); } node.thedef = g; - if (name == "eval" && tw.parent() instanceof AST_Call) { + if (name == "eval" && tw.parent() instanceof Cola.AST_Call) { for (var s = node.scope; s && !s.uses_eval; s = s.parent_scope) s.uses_eval = true; } @@ -180,10 +180,10 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){ self.walk(tw); }); -AST_Scope.DEFMETHOD("init_scope_vars", function(nesting){ +Cola.AST_Scope.DEFMETHOD("init_scope_vars", function(nesting){ this.directives = []; // contains the directives defined in this scope, i.e. "use strict" - this.variables = new Dictionary(); // map name to AST_SymbolVar (variables defined in this scope; includes functions) - this.functions = new Dictionary(); // map name to AST_SymbolDefun (functions defined in this scope) + this.variables = new Cola.Dictionary(); // map name to Cola.AST_SymbolVar (variables defined in this scope; includes functions) + this.functions = new Cola.Dictionary(); // map name to Cola.AST_SymbolDefun (functions defined in this scope) this.uses_with = false; // will be set to true if this or some nested scope uses the `with` statement this.uses_eval = false; // will be set to true if this or nested scope uses the global `eval` this.parent_scope = null; // the parent scope @@ -192,43 +192,43 @@ AST_Scope.DEFMETHOD("init_scope_vars", function(nesting){ this.nesting = nesting; // the nesting level of this scope (0 means toplevel) }); -AST_Scope.DEFMETHOD("strict", function(){ +Cola.AST_Scope.DEFMETHOD("strict", function(){ return this.has_directive("use strict"); }); -AST_Lambda.DEFMETHOD("init_scope_vars", function(){ - AST_Scope.prototype.init_scope_vars.apply(this, arguments); +Cola.AST_Lambda.DEFMETHOD("init_scope_vars", function(){ + Cola.AST_Scope.prototype.init_scope_vars.apply(this, arguments); this.uses_arguments = false; }); -AST_SymbolRef.DEFMETHOD("reference", function() { +Cola.AST_SymbolRef.DEFMETHOD("reference", function() { var def = this.definition(); def.references.push(this); var s = this.scope; while (s) { - push_uniq(s.enclosed, def); + Cola.push_uniq(s.enclosed, def); if (s === def.scope) break; s = s.parent_scope; } this.frame = this.scope.nesting - def.scope.nesting; }); -AST_Scope.DEFMETHOD("find_variable", function(name){ - if (name instanceof AST_Symbol) name = name.name; +Cola.AST_Scope.DEFMETHOD("find_variable", function(name){ + if (name instanceof Cola.AST_Symbol) name = name.name; return this.variables.get(name) || (this.parent_scope && this.parent_scope.find_variable(name)); }); -AST_Scope.DEFMETHOD("has_directive", function(value){ +Cola.AST_Scope.DEFMETHOD("has_directive", function(value){ return this.parent_scope && this.parent_scope.has_directive(value) || (this.directives.indexOf(value) >= 0 ? this : null); }); -AST_Scope.DEFMETHOD("def_function", function(symbol){ +Cola.AST_Scope.DEFMETHOD("def_function", function(symbol){ this.functions.set(symbol.name, this.def_variable(symbol)); }); -AST_Scope.DEFMETHOD("def_variable", function(symbol){ +Cola.AST_Scope.DEFMETHOD("def_variable", function(symbol){ var def; if (!this.variables.has(symbol.name)) { def = new SymbolDef(this, this.variables.size(), symbol); @@ -241,11 +241,11 @@ AST_Scope.DEFMETHOD("def_variable", function(symbol){ return symbol.thedef = def; }); -AST_Scope.DEFMETHOD("next_mangled", function(options){ +Cola.AST_Scope.DEFMETHOD("next_mangled", function(options){ var ext = this.enclosed; out: while (true) { var m = base54(++this.cname); - if (!is_identifier(m)) continue; // skip over "do" + if (!Cola.is_identifier(m)) continue; // skip over "do" // https://github.com/mishoo/UglifyJS2/issues/242 -- do not // shadow a name excepted from mangling. @@ -263,65 +263,65 @@ AST_Scope.DEFMETHOD("next_mangled", function(options){ } }); -AST_Function.DEFMETHOD("next_mangled", function(options, def){ +Cola.AST_Function.DEFMETHOD("next_mangled", function(options, def){ // #179, #326 // in Safari strict mode, something like (function x(x){...}) is a syntax error; // a function expression's argument cannot shadow the function expression's name - var tricky_def = def.orig[0] instanceof AST_SymbolFunarg && this.name && this.name.definition(); + var tricky_def = def.orig[0] instanceof Cola.AST_SymbolFunarg && this.name && this.name.definition(); while (true) { - var name = AST_Lambda.prototype.next_mangled.call(this, options, def); + var name = Cola.AST_Lambda.prototype.next_mangled.call(this, options, def); if (!(tricky_def && tricky_def.mangled_name == name)) return name; } }); -AST_Scope.DEFMETHOD("references", function(sym){ - if (sym instanceof AST_Symbol) sym = sym.definition(); +Cola.AST_Scope.DEFMETHOD("references", function(sym){ + if (sym instanceof Cola.AST_Symbol) sym = sym.definition(); return this.enclosed.indexOf(sym) < 0 ? null : sym; }); -AST_Symbol.DEFMETHOD("unmangleable", function(options){ +Cola.AST_Symbol.DEFMETHOD("unmangleable", function(options){ return this.definition().unmangleable(options); }); // property accessors are not mangleable -AST_SymbolAccessor.DEFMETHOD("unmangleable", function(){ +Cola.AST_SymbolAccessor.DEFMETHOD("unmangleable", function(){ return true; }); // labels are always mangleable -AST_Label.DEFMETHOD("unmangleable", function(){ +Cola.AST_Label.DEFMETHOD("unmangleable", function(){ return false; }); -AST_Symbol.DEFMETHOD("unreferenced", function(){ +Cola.AST_Symbol.DEFMETHOD("unreferenced", function(){ return this.definition().references.length == 0 && !(this.scope.uses_eval || this.scope.uses_with); }); -AST_Symbol.DEFMETHOD("undeclared", function(){ +Cola.AST_Symbol.DEFMETHOD("undeclared", function(){ return this.definition().undeclared; }); -AST_LabelRef.DEFMETHOD("undeclared", function(){ +Cola.AST_LabelRef.DEFMETHOD("undeclared", function(){ return false; }); -AST_Label.DEFMETHOD("undeclared", function(){ +Cola.AST_Label.DEFMETHOD("undeclared", function(){ return false; }); -AST_Symbol.DEFMETHOD("definition", function(){ +Cola.AST_Symbol.DEFMETHOD("definition", function(){ return this.thedef; }); -AST_Symbol.DEFMETHOD("global", function(){ +Cola.AST_Symbol.DEFMETHOD("global", function(){ return this.definition().global; }); -AST_Toplevel.DEFMETHOD("_default_mangler_options", function(options){ - return defaults(options, { +Cola.AST_Toplevel.DEFMETHOD("_default_mangler_options", function(options){ + return Cola.defaults(options, { except : [], eval : false, sort : false, @@ -330,23 +330,23 @@ AST_Toplevel.DEFMETHOD("_default_mangler_options", function(options){ }); }); -AST_Toplevel.DEFMETHOD("mangle_names", function(options){ +Cola.AST_Toplevel.DEFMETHOD("mangle_names", function(options){ options = this._default_mangler_options(options); // We only need to mangle declaration nodes. Special logic wired // into the code generator will display the mangled name if it's - // present (and for AST_SymbolRef-s it'll use the mangled name of - // the AST_SymbolDeclaration that it points to). + // present (and for Cola.AST_SymbolRef-s it'll use the mangled name of + // the Cola.AST_SymbolDeclaration that it points to). var lname = -1; var to_mangle = []; - var tw = new TreeWalker(function(node, descend){ - if (node instanceof AST_LabeledStatement) { - // lname is incremented when we get to the AST_Label + var tw = new Cola.TreeWalker(function(node, descend){ + if (node instanceof Cola.AST_LabeledStatement) { + // lname is incremented when we get to the Cola.AST_Label var save_nesting = lname; descend(); lname = save_nesting; - return true; // don't descend again in TreeWalker + return true; // don't descend again in Cola.TreeWalker } - if (node instanceof AST_Scope) { + if (node instanceof Cola.AST_Scope) { var p = tw.parent(), a = []; node.variables.each(function(symbol){ if (options.except.indexOf(symbol.name) < 0) { @@ -359,13 +359,13 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options){ to_mangle.push.apply(to_mangle, a); return; } - if (node instanceof AST_Label) { + if (node instanceof Cola.AST_Label) { var name; - do name = base54(++lname); while (!is_identifier(name)); + do name = base54(++lname); while (!Cola.is_identifier(name)); node.mangled_name = name; return true; } - if (options.screw_ie8 && node instanceof AST_SymbolCatch) { + if (options.screw_ie8 && node instanceof Cola.AST_SymbolCatch) { to_mangle.push(node.definition()); return; } @@ -374,70 +374,70 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options){ to_mangle.forEach(function(def){ def.mangle(options) }); }); -AST_Toplevel.DEFMETHOD("compute_char_frequency", function(options){ +Cola.AST_Toplevel.DEFMETHOD("compute_char_frequency", function(options){ options = this._default_mangler_options(options); - var tw = new TreeWalker(function(node){ - if (node instanceof AST_Constant) + var tw = new Cola.TreeWalker(function(node){ + if (node instanceof Cola.AST_Constant) base54.consider(node.print_to_string()); - else if (node instanceof AST_Return) + else if (node instanceof Cola.AST_Return) base54.consider("return"); - else if (node instanceof AST_Throw) + else if (node instanceof Cola.AST_Throw) base54.consider("throw"); - else if (node instanceof AST_Continue) + else if (node instanceof Cola.AST_Continue) base54.consider("continue"); - else if (node instanceof AST_Break) + else if (node instanceof Cola.AST_Break) base54.consider("break"); - else if (node instanceof AST_Debugger) + else if (node instanceof Cola.AST_Debugger) base54.consider("debugger"); - else if (node instanceof AST_Directive) + else if (node instanceof Cola.AST_Directive) base54.consider(node.value); - else if (node instanceof AST_While) + else if (node instanceof Cola.AST_While) base54.consider("while"); - else if (node instanceof AST_Do) + else if (node instanceof Cola.AST_Do) base54.consider("do while"); - else if (node instanceof AST_If) { + else if (node instanceof Cola.AST_If) { base54.consider("if"); if (node.alternative) base54.consider("else"); } - else if (node instanceof AST_Var) + else if (node instanceof Cola.AST_Var) base54.consider("var"); - else if (node instanceof AST_Const) + else if (node instanceof Cola.AST_Const) base54.consider("const"); - else if (node instanceof AST_Lambda) + else if (node instanceof Cola.AST_Lambda) base54.consider("function"); - else if (node instanceof AST_For) + else if (node instanceof Cola.AST_For) base54.consider("for"); - else if (node instanceof AST_ForIn) + else if (node instanceof Cola.AST_ForIn) base54.consider("for in"); - else if (node instanceof AST_Switch) + else if (node instanceof Cola.AST_Switch) base54.consider("switch"); - else if (node instanceof AST_Case) + else if (node instanceof Cola.AST_Case) base54.consider("case"); - else if (node instanceof AST_Default) + else if (node instanceof Cola.AST_Default) base54.consider("default"); - else if (node instanceof AST_With) + else if (node instanceof Cola.AST_With) base54.consider("with"); - else if (node instanceof AST_ObjectSetter) + else if (node instanceof Cola.AST_ObjectSetter) base54.consider("set" + node.key); - else if (node instanceof AST_ObjectGetter) + else if (node instanceof Cola.AST_ObjectGetter) base54.consider("get" + node.key); - else if (node instanceof AST_ObjectKeyVal) + else if (node instanceof Cola.AST_ObjectKeyVal) base54.consider(node.key); - else if (node instanceof AST_New) + else if (node instanceof Cola.AST_New) base54.consider("new"); - else if (node instanceof AST_This) + else if (node instanceof Cola.AST_This) base54.consider("this"); - else if (node instanceof AST_Try) + else if (node instanceof Cola.AST_Try) base54.consider("try"); - else if (node instanceof AST_Catch) + else if (node instanceof Cola.AST_Catch) base54.consider("catch"); - else if (node instanceof AST_Finally) + else if (node instanceof Cola.AST_Finally) base54.consider("finally"); - else if (node instanceof AST_Symbol && node.unmangleable(options)) + else if (node instanceof Cola.AST_Symbol && node.unmangleable(options)) base54.consider(node.name); - else if (node instanceof AST_Unary || node instanceof AST_Binary) + else if (node instanceof Cola.AST_Unary || node instanceof Cola.AST_Binary) base54.consider(node.operator); - else if (node instanceof AST_Dot) + else if (node instanceof Cola.AST_Dot) base54.consider(node.property); }); this.walk(tw); @@ -459,9 +459,9 @@ var base54 = (function() { } }; base54.sort = function() { - chars = mergeSort(chars, function(a, b){ - if (is_digit(a) && !is_digit(b)) return 1; - if (is_digit(b) && !is_digit(a)) return -1; + chars = Cola.mergeSort(chars, function(a, b){ + if (Cola.is_digit(a) && !Cola.is_digit(b)) return 1; + if (Cola.is_digit(b) && !Cola.is_digit(a)) return -1; return frequency[b] - frequency[a]; }); }; @@ -481,8 +481,8 @@ var base54 = (function() { return base54; })(); -AST_Toplevel.DEFMETHOD("scope_warnings", function(options){ - options = defaults(options, { +Cola.AST_Toplevel.DEFMETHOD("scope_warnings", function(options){ + options = Cola.defaults(options, { undeclared : false, // this makes a lot of noise unreferenced : true, assign_to_global : true, @@ -490,15 +490,15 @@ AST_Toplevel.DEFMETHOD("scope_warnings", function(options){ nested_defuns : true, eval : true }); - var tw = new TreeWalker(function(node){ + var tw = new Cola.TreeWalker(function(node){ if (options.undeclared - && node instanceof AST_SymbolRef + && node instanceof Cola.AST_SymbolRef && node.undeclared()) { // XXX: this also warns about JS standard names, // i.e. Object, Array, parseInt etc. Should add a list of // exceptions. - AST_Node.warn("Undeclared symbol: {name} [{file}:{line},{col}]", { + Cola.AST_Node.warn("Undeclared symbol: {name} [{file}:{line},{col}]", { name: node.name, file: node.start.file, line: node.start.line, @@ -508,14 +508,14 @@ AST_Toplevel.DEFMETHOD("scope_warnings", function(options){ if (options.assign_to_global) { var sym = null; - if (node instanceof AST_Assign && node.left instanceof AST_SymbolRef) + if (node instanceof Cola.AST_Assign && node.left instanceof Cola.AST_SymbolRef) sym = node.left; - else if (node instanceof AST_ForIn && node.init instanceof AST_SymbolRef) + else if (node instanceof Cola.AST_ForIn && node.init instanceof Cola.AST_SymbolRef) sym = node.init; if (sym && (sym.undeclared() || (sym.global() && sym.scope !== sym.definition().scope))) { - AST_Node.warn("{msg}: {name} [{file}:{line},{col}]", { + Cola.AST_Node.warn("{msg}: {name} [{file}:{line},{col}]", { msg: sym.undeclared() ? "Accidental global?" : "Assignment to global", name: sym.name, file: sym.start.file, @@ -525,16 +525,16 @@ AST_Toplevel.DEFMETHOD("scope_warnings", function(options){ } } if (options.eval - && node instanceof AST_SymbolRef + && node instanceof Cola.AST_SymbolRef && node.undeclared() && node.name == "eval") { - AST_Node.warn("Eval is used [{file}:{line},{col}]", node.start); + Cola.AST_Node.warn("Eval is used [{file}:{line},{col}]", node.start); } if (options.unreferenced - && (node instanceof AST_SymbolDeclaration || node instanceof AST_Label) + && (node instanceof Cola.AST_SymbolDeclaration || node instanceof Cola.AST_Label) && node.unreferenced()) { - AST_Node.warn("{type} {name} is declared but not referenced [{file}:{line},{col}]", { - type: node instanceof AST_Label ? "Label" : "Symbol", + Cola.AST_Node.warn("{type} {name} is declared but not referenced [{file}:{line},{col}]", { + type: node instanceof Cola.AST_Label ? "Label" : "Symbol", name: node.name, file: node.start.file, line: node.start.line, @@ -542,9 +542,9 @@ AST_Toplevel.DEFMETHOD("scope_warnings", function(options){ }); } if (options.func_arguments - && node instanceof AST_Lambda + && node instanceof Cola.AST_Lambda && node.uses_arguments) { - AST_Node.warn("arguments used in function {name} [{file}:{line},{col}]", { + Cola.AST_Node.warn("arguments used in function {name} [{file}:{line},{col}]", { name: node.name ? node.name.name : "anonymous", file: node.start.file, line: node.start.line, @@ -552,9 +552,9 @@ AST_Toplevel.DEFMETHOD("scope_warnings", function(options){ }); } if (options.nested_defuns - && node instanceof AST_Defun - && !(tw.parent() instanceof AST_Scope)) { - AST_Node.warn("Function {name} declared in nested statement \"{type}\" [{file}:{line},{col}]", { + && node instanceof Cola.AST_Defun + && !(tw.parent() instanceof Cola.AST_Scope)) { + Cola.AST_Node.warn("Function {name} declared in nested statement \"{type}\" [{file}:{line},{col}]", { name: node.name.name, type: tw.parent().TYPE, file: node.start.file, diff --git a/lib/sourcemap.js b/lib/sourcemap.js index 663ef12e..f4deb21b 100644 --- a/lib/sourcemap.js +++ b/lib/sourcemap.js @@ -45,7 +45,7 @@ // a small wrapper around fitzgen's source-map library function SourceMap(options) { - options = defaults(options, { + options = Cola.defaults(options, { file : null, root : null, orig : null, diff --git a/lib/transform.js b/lib/transform.js index c3c34f58..886bfd8c 100644 --- a/lib/transform.js +++ b/lib/transform.js @@ -46,11 +46,11 @@ // Tree transformer helpers. function TreeTransformer(before, after) { - TreeWalker.call(this); + Cola.TreeWalker.call(this); this.before = before; this.after = after; } -TreeTransformer.prototype = new TreeWalker; +TreeTransformer.prototype = new Cola.TreeWalker; (function(undefined){ @@ -76,142 +76,142 @@ TreeTransformer.prototype = new TreeWalker; }; function do_list(list, tw) { - return MAP(list, function(node){ + return Cola.MAP(list, function(node){ return node.transform(tw, true); }); }; - _(AST_Node, noop); + _(Cola.AST_Node, Cola.noop); - _(AST_LabeledStatement, function(self, tw){ + _(Cola.AST_LabeledStatement, function(self, tw){ self.label = self.label.transform(tw); self.body = self.body.transform(tw); }); - _(AST_SimpleStatement, function(self, tw){ + _(Cola.AST_SimpleStatement, function(self, tw){ self.body = self.body.transform(tw); }); - _(AST_Block, function(self, tw){ + _(Cola.AST_Block, function(self, tw){ self.body = do_list(self.body, tw); }); - _(AST_DWLoop, function(self, tw){ + _(Cola.AST_DWLoop, function(self, tw){ self.condition = self.condition.transform(tw); self.body = self.body.transform(tw); }); - _(AST_For, function(self, tw){ + _(Cola.AST_For, function(self, tw){ if (self.init) self.init = self.init.transform(tw); if (self.condition) self.condition = self.condition.transform(tw); if (self.step) self.step = self.step.transform(tw); self.body = self.body.transform(tw); }); - _(AST_ForIn, function(self, tw){ + _(Cola.AST_ForIn, function(self, tw){ self.init = self.init.transform(tw); self.object = self.object.transform(tw); self.body = self.body.transform(tw); }); - _(AST_With, function(self, tw){ + _(Cola.AST_With, function(self, tw){ self.expression = self.expression.transform(tw); self.body = self.body.transform(tw); }); - _(AST_Exit, function(self, tw){ + _(Cola.AST_Exit, function(self, tw){ if (self.value) self.value = self.value.transform(tw); }); - _(AST_LoopControl, function(self, tw){ + _(Cola.AST_LoopControl, function(self, tw){ if (self.label) self.label = self.label.transform(tw); }); - _(AST_If, function(self, tw){ + _(Cola.AST_If, function(self, tw){ self.condition = self.condition.transform(tw); self.body = self.body.transform(tw); if (self.alternative) self.alternative = self.alternative.transform(tw); }); - _(AST_Switch, function(self, tw){ + _(Cola.AST_Switch, function(self, tw){ self.expression = self.expression.transform(tw); self.body = do_list(self.body, tw); }); - _(AST_Case, function(self, tw){ + _(Cola.AST_Case, function(self, tw){ self.expression = self.expression.transform(tw); self.body = do_list(self.body, tw); }); - _(AST_Try, function(self, tw){ + _(Cola.AST_Try, function(self, tw){ self.body = do_list(self.body, tw); if (self.bcatch) self.bcatch = self.bcatch.transform(tw); if (self.bfinally) self.bfinally = self.bfinally.transform(tw); }); - _(AST_Catch, function(self, tw){ + _(Cola.AST_Catch, function(self, tw){ self.argname = self.argname.transform(tw); self.body = do_list(self.body, tw); }); - _(AST_Definitions, function(self, tw){ + _(Cola.AST_Definitions, function(self, tw){ self.definitions = do_list(self.definitions, tw); }); - _(AST_VarDef, function(self, tw){ + _(Cola.AST_VarDef, function(self, tw){ self.name = self.name.transform(tw); if (self.value) self.value = self.value.transform(tw); }); - _(AST_Lambda, function(self, tw){ + _(Cola.AST_Lambda, function(self, tw){ if (self.name) self.name = self.name.transform(tw); self.argnames = do_list(self.argnames, tw); self.body = do_list(self.body, tw); }); - _(AST_Call, function(self, tw){ + _(Cola.AST_Call, function(self, tw){ self.expression = self.expression.transform(tw); self.args = do_list(self.args, tw); }); - _(AST_Seq, function(self, tw){ + _(Cola.AST_Seq, function(self, tw){ self.car = self.car.transform(tw); self.cdr = self.cdr.transform(tw); }); - _(AST_Dot, function(self, tw){ + _(Cola.AST_Dot, function(self, tw){ self.expression = self.expression.transform(tw); }); - _(AST_Sub, function(self, tw){ + _(Cola.AST_Sub, function(self, tw){ self.expression = self.expression.transform(tw); self.property = self.property.transform(tw); }); - _(AST_Unary, function(self, tw){ + _(Cola.AST_Unary, function(self, tw){ self.expression = self.expression.transform(tw); }); - _(AST_Binary, function(self, tw){ + _(Cola.AST_Binary, function(self, tw){ self.left = self.left.transform(tw); self.right = self.right.transform(tw); }); - _(AST_Conditional, function(self, tw){ + _(Cola.AST_Conditional, function(self, tw){ self.condition = self.condition.transform(tw); self.consequent = self.consequent.transform(tw); self.alternative = self.alternative.transform(tw); }); - _(AST_Array, function(self, tw){ + _(Cola.AST_Array, function(self, tw){ self.elements = do_list(self.elements, tw); }); - _(AST_Object, function(self, tw){ + _(Cola.AST_Object, function(self, tw){ self.properties = do_list(self.properties, tw); }); - _(AST_ObjectProperty, function(self, tw){ + _(Cola.AST_ObjectProperty, function(self, tw){ self.value = self.value.transform(tw); }); diff --git a/lib/translate.js b/lib/translate.js index a3b0c88a..ec35b194 100644 --- a/lib/translate.js +++ b/lib/translate.js @@ -41,114 +41,114 @@ function translate(tree){ var tt = new TreeTransformer(null, function(node){ var newNode, props; - if(node instanceof AST_Binary && node.operator == '**'){ + if(node instanceof Cola.AST_Binary && node.operator == '**'){ props = { args : [node.left, node.right], - start : new AST_Token({ nlb : false, type : 'name', value : 'Math' }), - end : new AST_Token({ nlb : false, type : 'punc', value : ')' }) + start : new Cola.AST_Token({ nlb : false, type : 'name', value : 'Math' }), + end : new Cola.AST_Token({ nlb : false, type : 'punc', value : ')' }) }; - props.expression = new AST_Dot({ + props.expression = new Cola.AST_Dot({ property : 'pow', start : props.start, - end : new AST_Token({ nlb : false, type : 'name', value : 'pow' }), - expression : new AST_SymbolRef({ name : 'Math', start : props.start, end : props.start }) + end : new Cola.AST_Token({ nlb : false, type : 'name', value : 'pow' }), + expression : new Cola.AST_SymbolRef({ name : 'Math', start : props.start, end : props.start }) }); - node = new AST_Call(props); + node = new Cola.AST_Call(props); } else - if(node instanceof AST_Binary && node.operator == '%%'){ + if(node instanceof Cola.AST_Binary && node.operator == '%%'){ props = { args : [node.left, node.right], - start : new AST_Token({ nlb : false, type : 'name', value : '$_cola_modulo' }), - end : new AST_Token({ nlb : false, type : 'punc', value : ')' }) + start : new Cola.AST_Token({ nlb : false, type : 'name', value : '$_cola_modulo' }), + end : new Cola.AST_Token({ nlb : false, type : 'punc', value : ')' }) }; - props.expression = new AST_SymbolRef({ + props.expression = new Cola.AST_SymbolRef({ name : '$_cola_modulo', start : props.start, end : props.start }); - node = new AST_Call(props); + node = new Cola.AST_Call(props); } else - if(node instanceof AST_SimpleStatement && node.body instanceof AST_Assign && node.body.operator == '?='){ + if(node instanceof Cola.AST_SimpleStatement && node.body instanceof Cola.AST_Assign && node.body.operator == '?='){ node.body.operator = '='; props = { args : [node.body.left], - start : new AST_Token({ nlb : false, type : 'name', value : '$_cola_isntset' }), - end : new AST_Token({ nlb : false, type : 'punc', value : ')' }) + start : new Cola.AST_Token({ nlb : false, type : 'name', value : '$_cola_isntset' }), + end : new Cola.AST_Token({ nlb : false, type : 'punc', value : ')' }) }; - props.expression = new AST_SymbolRef({ + props.expression = new Cola.AST_SymbolRef({ name : '$_cola_isntset', start : props.start, end : props.start }); - node = new AST_If({ + node = new Cola.AST_If({ body : node.clone(), - start : new AST_Token({ nlb : false, type : 'keyword', value : 'if' }), - end : new AST_Token({ nlb : false, type : 'punc', value : ';' }), - condition : new AST_Call(props) + start : new Cola.AST_Token({ nlb : false, type : 'keyword', value : 'if' }), + end : new Cola.AST_Token({ nlb : false, type : 'punc', value : ';' }), + condition : new Cola.AST_Call(props) }); } else - if(node instanceof AST_Assign && node.operator == '?='){ + if(node instanceof Cola.AST_Assign && node.operator == '?='){ node.operator = '='; props = { args : [node.left], - start : new AST_Token({ nlb : false, type : 'name', value : '$_cola_isntset' }), - end : new AST_Token({ nlb : false, type : 'punc', value : ')' }) + start : new Cola.AST_Token({ nlb : false, type : 'name', value : '$_cola_isntset' }), + end : new Cola.AST_Token({ nlb : false, type : 'punc', value : ')' }) }; - props.expression = new AST_SymbolRef({ + props.expression = new Cola.AST_SymbolRef({ name : '$_cola_isntset', start : props.start, end : props.start }); - node = new AST_Conditional({ - start : new AST_Token({ nlb : false, type : 'punc', value : '(' }), - end : new AST_Token({ nlb : false, type : 'punc', value : ')' }), - condition : new AST_Call(props), + node = new Cola.AST_Conditional({ + start : new Cola.AST_Token({ nlb : false, type : 'punc', value : '(' }), + end : new Cola.AST_Token({ nlb : false, type : 'punc', value : ')' }), + condition : new Cola.AST_Call(props), consequent : node.clone(), alternative : node.left }); } else - if(node instanceof AST_Binary && node.operator == 'is'){ + if(node instanceof Cola.AST_Binary && node.operator == 'is'){ props = { args : [node.left, node.right], - start : new AST_Token({ nlb : false, type : 'name', value : '$_cola_is' }), - end : new AST_Token({ nlb : false, type : 'punc', value : ')' }) + start : new Cola.AST_Token({ nlb : false, type : 'name', value : '$_cola_is' }), + end : new Cola.AST_Token({ nlb : false, type : 'punc', value : ')' }) }; - props.expression = new AST_SymbolRef({ + props.expression = new Cola.AST_SymbolRef({ name : '$_cola_is', start : props.start, end : props.start }); - node = new AST_Call(props); + node = new Cola.AST_Call(props); } else - if(node instanceof AST_Binary && node.operator == 'isnt'){ + if(node instanceof Cola.AST_Binary && node.operator == 'isnt'){ props = { args : [node.left, node.right], - start : new AST_Token({ nlb : false, type : 'name', value : '$_cola_isnt' }), - end : new AST_Token({ nlb : false, type : 'punc', value : ')' }) + start : new Cola.AST_Token({ nlb : false, type : 'name', value : '$_cola_isnt' }), + end : new Cola.AST_Token({ nlb : false, type : 'punc', value : ')' }) }; - props.expression = new AST_SymbolRef({ + props.expression = new Cola.AST_SymbolRef({ name : '$_cola_isnt', start : props.start, end : props.start }); - node = new AST_Call(props); + node = new Cola.AST_Call(props); } else - if(node instanceof AST_StringTemplate){ - newNode = new AST_Binary({ + if(node instanceof Cola.AST_StringTemplate){ + newNode = new Cola.AST_Binary({ operator : '+', left : node.body[0], right : node.body[1], @@ -156,7 +156,7 @@ function translate(tree){ end : node.body[1].end }); for(var i = 2; i < node.body.length; i++) - newNode = new AST_Binary({ + newNode = new Cola.AST_Binary({ operator : '+', left : newNode, right : node.body[i], @@ -167,7 +167,7 @@ function translate(tree){ node = newNode; } else - if(node instanceof AST_RegExp && (node.value.indexOf('\n') != -1 || /\/[\w]*x[\w]*$/.test(node.value))){ + if(node instanceof Cola.AST_RegExp && (node.value.indexOf('\n') != -1 || /\/[\w]*x[\w]*$/.test(node.value))){ node.value = node.value.replace(/[\r\n\s]/g,'').replace(/(\/[\w]*)x([\w]*$)/, '$1$2'); } diff --git a/lib/utils.js b/lib/utils.js index 4a1bdec0..b8421781 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -42,79 +42,80 @@ ***********************************************************************/ "use strict"; +!window.Cola && (window.Cola = {}); -function array_to_hash(a) { +Cola.array_to_hash = function (a) { var ret = Object.create(null); for (var i = 0; i < a.length; ++i) ret[a[i]] = true; return ret; }; -function slice(a, start) { +Cola.slice = function (a, start) { return Array.prototype.slice.call(a, start || 0); }; -function characters(str) { +Cola.characters = function (str) { return str.split(""); }; -function member(name, array) { +Cola.member = function (name, array) { for (var i = array.length; --i >= 0;) if (array[i] == name) return true; return false; }; -function find_if(func, array) { +Cola.find_if = function (func, array) { for (var i = 0, n = array.length; i < n; ++i) { if (func(array[i])) return array[i]; } }; -function repeat_string(str, i) { +Cola.repeat_string = function (str, i) { if (i <= 0) return ""; if (i == 1) return str; - var d = repeat_string(str, i >> 1); + var d = Cola.repeat_string(str, i >> 1); d += d; if (i & 1) d += str; return d; }; -function DefaultsError(msg, defs) { +Cola.DefaultsError = function (msg, defs) { Error.call(this, msg); this.msg = msg; this.defs = defs; }; -DefaultsError.prototype = Object.create(Error.prototype); -DefaultsError.prototype.constructor = DefaultsError; +Cola.DefaultsError.prototype = Object.create(Error.prototype); +Cola.DefaultsError.prototype.constructor = Cola.DefaultsError; -DefaultsError.croak = function(msg, defs) { - throw new DefaultsError(msg, defs); +Cola.DefaultsError.croak = function(msg, defs) { + throw new Cola.DefaultsError(msg, defs); }; -function defaults(args, defs, croak) { +Cola.defaults = function (args, defs, croak) { if (args === true) args = {}; var ret = args || {}; if (croak) for (var i in ret) if (ret.hasOwnProperty(i) && !defs.hasOwnProperty(i)) - DefaultsError.croak("`" + i + "` is not a supported option", defs); + Cola.DefaultsError.croak("`" + i + "` is not a supported option", defs); for (var i in defs) if (defs.hasOwnProperty(i)) { ret[i] = (args && args.hasOwnProperty(i)) ? args[i] : defs[i]; } return ret; }; -function merge(obj, ext) { +Cola.merge = function (obj, ext) { for (var i in ext) if (ext.hasOwnProperty(i)) { obj[i] = ext[i]; } return obj; }; -function noop() {}; +Cola.noop = function () {}; -var MAP = (function(){ +Cola.MAP = (function(){ function MAP(a, f, backwards) { var ret = [], top = [], i; function doit() { @@ -162,24 +163,24 @@ var MAP = (function(){ return MAP; })(); -function push_uniq(array, el) { +Cola.push_uniq = function (array, el) { if (array.indexOf(el) < 0) array.push(el); }; -function string_template(text, props) { +Cola.string_template = function (text, props) { return text.replace(/\{(.+?)\}/g, function(str, p){ return props[p]; }); }; -function remove(array, el) { +Cola.remove = function (array, el) { for (var i = array.length; --i >= 0;) { if (array[i] === el) array.splice(i, 1); } }; -function mergeSort(array, cmp) { +Cola.mergeSort = function (array, cmp) { if (array.length < 2) return array.slice(); function merge(a, b) { var r = [], ai = 0, bi = 0, i = 0; @@ -203,13 +204,13 @@ function mergeSort(array, cmp) { return _ms(array); }; -function set_difference(a, b) { +Cola.set_difference = function (a, b) { return a.filter(function(el){ return b.indexOf(el) < 0; }); }; -function set_intersection(a, b) { +Cola.set_intersection = function (a, b) { return a.filter(function(el){ return b.indexOf(el) >= 0; }); @@ -217,7 +218,7 @@ function set_intersection(a, b) { // this function is taken from Acorn [1], written by Marijn Haverbeke // [1] https://github.com/marijnh/acorn -function makePredicate(words) { +Cola.makePredicate = function (words) { if (!(words instanceof Array)) words = words.split(" "); var f = "", cats = []; out: for (var i = 0; i < words.length; ++i) { @@ -252,18 +253,18 @@ function makePredicate(words) { return new Function("str", f); }; -function all(array, predicate) { +Cola.all = function (array, predicate) { for (var i = array.length; --i >= 0;) if (!predicate(array[i])) return false; return true; }; -function Dictionary() { +Cola.Dictionary = function () { this._values = Object.create(null); this._size = 0; }; -Dictionary.prototype = { +Cola.Dictionary.prototype = { set: function(key, val) { if (!this.has(key)) ++this._size; this._values["$" + key] = val;