tree transformer api (WIP)
authorMihai Bazon <mihai@bazon.net>
Sat, 22 Sep 2012 10:32:32 +0000 (13:32 +0300)
committerMihai Bazon <mihai@bazon.net>
Sat, 22 Sep 2012 16:41:09 +0000 (19:41 +0300)
lib/compress.js
lib/transform.js [new file with mode: 0644]
tmp/test-node.js
tools/node.js

index 5b0e06a..6813925 100644 (file)
@@ -1014,6 +1014,7 @@ function Compressor(options, false_by_default) {
         self = self.clone();
         self.expression = self.expression.squeeze(compressor);
         self.body = self.body.squeeze(compressor);
+        return self;
     });
 
     SQUEEZE(AST_Exit, function(self, compressor){
@@ -1569,13 +1570,6 @@ function Compressor(options, false_by_default) {
         return self;
     });
 
-    SQUEEZE(AST_Assign, function(self, compressor){
-        self = self.clone();
-        self.left = self.left.squeeze(compressor);
-        self.right = self.right.squeeze(compressor);
-        return self.optimize(compressor);
-    });
-
     SQUEEZE(AST_SymbolRef, function(self, compressor){
         return self.optimize(compressor);
     });
diff --git a/lib/transform.js b/lib/transform.js
new file mode 100644 (file)
index 0000000..743dd6e
--- /dev/null
@@ -0,0 +1,226 @@
+/***********************************************************************
+
+  A JavaScript tokenizer / parser / beautifier / compressor.
+  https://github.com/mishoo/UglifyJS2
+
+  -------------------------------- (C) ---------------------------------
+
+                           Author: Mihai Bazon
+                         <mihai.bazon@gmail.com>
+                       http://mihai.bazon.net/blog
+
+  Distributed under the BSD license:
+
+    Copyright 2012 (c) Mihai Bazon <mihai.bazon@gmail.com>
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions
+    are met:
+
+        * Redistributions of source code must retain the above
+          copyright notice, this list of conditions and the following
+          disclaimer.
+
+        * Redistributions in binary form must reproduce the above
+          copyright notice, this list of conditions and the following
+          disclaimer in the documentation and/or other materials
+          provided with the distribution.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
+    EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+    PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
+    LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+    OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+    TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+    THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+    SUCH DAMAGE.
+
+ ***********************************************************************/
+
+// Tree transformer helpers.
+// XXX: eventually I should refactor the compressor to use this infrastructure.
+
+function TreeTransformer(before, after) {
+    this.before = before;
+    this.after = after;
+    this.stack = [];
+}
+
+TreeTransformer.prototype = {
+    push: function (node) {
+        this.stack.push(node);
+    },
+    pop: function() {
+        return this.stack.pop();
+    },
+    parent: function (n) {
+        return this.stack[this.stack.length - 2 - (n || 0)];
+    }
+};
+
+(function(undefined){
+
+    function _(node, descend) {
+        node.DEFMETHOD("transform", function(tw, in_list){
+            var x, y;
+            tw.push(this);
+            x = tw.before(this, function(){
+                descend(x, tw);
+            }, in_list);
+            if (x === undefined) {
+                x = this.clone();
+                descend(x, tw);
+                y = tw.after(this, in_list);
+                if (y !== undefined) x = y;
+            }
+            tw.pop();
+            return x;
+        });
+    };
+
+    function do_list(list, tw) {
+        return MAP(list, function(node){
+            return node.transform(tw, true);
+        });
+    };
+
+    _(AST_Node, noop);
+
+    _(AST_LabeledStatement, function(self, tw){
+        self.label = self.label.transform(tw);
+        self.body = self.body.transform(tw);
+    });
+
+    _(AST_SimpleStatement, function(self, tw){
+        self.body = self.body.transform(tw);
+    });
+
+    _(AST_BlockStatement, function(self, tw){
+        self.body = do_list(self.body, tw);
+    });
+
+    _(AST_Block, function(self, tw){
+        self.body = do_list(self.body, tw);
+    });
+
+    _(AST_DWLoop, function(self, tw){
+        self.condition = self.condition.transform(tw);
+        self.body = self.body.transform(tw);
+    });
+
+    _(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){
+        self.init = self.init.transform(tw);
+        self.object = self.object.transform(tw);
+        self.body = self.body.transform(tw);
+    });
+
+    _(AST_With, function(self, tw){
+        self.expression = self.expression.transform(tw);
+        self.body = self.body.transform(tw);
+    });
+
+    _(AST_Exit, function(self, tw){
+        if (self.value) self.value = self.value.transform(tw);
+    });
+
+    _(AST_LoopControl, function(self, tw){
+        if (self.label) self.label = self.label.transform(tw);
+    });
+
+    _(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){
+        self.expression = self.expression.transform(tw);
+        self.body = self.body.transform(tw);
+    });
+
+    _(AST_Case, function(self, tw){
+        self.expression = self.expression.transform(tw);
+        self.body = do_list(self.body, tw);
+    });
+
+    _(AST_Try, function(self, tw){
+        self.body = do_list(self.body, tw);
+    });
+
+    _(AST_Catch, function(self, tw){
+        self.argname = self.argname.transform(tw);
+        self.body = do_list(self.body, tw);
+    });
+
+    _(AST_Definitions, function(self, tw){
+        self.definitions = do_list(self.definitions, tw);
+    });
+
+    _(AST_VarDef, function(self, tw){
+        if (self.value) self.value = self.value.transform(tw);
+    });
+
+    _(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){
+        self.expression = self.expression.transform(tw);
+        self.args = do_list(self.args, tw);
+    });
+
+    _(AST_Seq, function(self, tw){
+        self.car = self.car.transform(tw);
+        self.cdr = self.cdr.transform(tw);
+    });
+
+    _(AST_Dot, function(self, tw){
+        self.expression = self.expression.transform(tw);
+    });
+
+    _(AST_Sub, function(self, tw){
+        self.expression = self.expression.transform(tw);
+        self.property = self.property.transform(tw);
+    });
+
+    _(AST_Unary, function(self, tw){
+        self.expression = self.expression.transform(tw);
+    });
+
+    _(AST_Binary, function(self, tw){
+        self.left = self.left.transform(tw);
+        self.right = self.right.transform(tw);
+    });
+
+    _(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){
+        self.elements = do_list(self.elements, tw);
+    });
+
+    _(AST_Object, function(self, tw){
+        self.properties = do_list(self.properties, tw);
+    });
+
+    _(AST_ObjectProperty, function(self, tw){
+        self.value = self.value.transform(tw);
+    });
+
+})();
index fdabafb..f2e0626 100755 (executable)
@@ -9,15 +9,31 @@ var filename = process.argv[2];
 var code = fs.readFileSync(filename, "utf8");
 
 var ast = UglifyJS.parse(code);
-ast.figure_out_scope();
-ast = ast.squeeze(UglifyJS.Compressor());
 
-ast.compute_char_frequency();
-UglifyJS.base54.sort();
+var tt = new UglifyJS.TreeTransformer(
+    function before(node, descend) {
+        if (node instanceof UglifyJS.AST_Var) {
+            //return new UglifyJS.AST_EmptyStatement(node);
+            return UglifyJS.MAP.skip;
+        }
+    },
+    function after(node) {
+        console.log("After ", node.TYPE);
+    }
+);
 
-ast.figure_out_scope();
-ast.scope_warnings();
-ast.mangle_names();
+var x = ast.transform(tt);
+sys.print(x.print_to_string({ beautify: true }));
 
-sys.error(UglifyJS.base54.get());
-sys.print(ast.print_to_string({ beautify: true }));
+// ast.figure_out_scope();
+// ast = ast.squeeze(UglifyJS.Compressor());
+
+// ast.compute_char_frequency();
+// UglifyJS.base54.sort();
+
+// ast.figure_out_scope();
+// ast.scope_warnings();
+// ast.mangle_names();
+
+// sys.error(UglifyJS.base54.get());
+// sys.print(ast.print_to_string({ beautify: true }));
index c8d3bd8..0185d04 100644 (file)
@@ -26,6 +26,7 @@ function load_global(file) {
 load_global("../lib/utils.js");
 load_global("../lib/ast.js");
 load_global("../lib/parse.js");
+load_global("../lib/transform.js");
 load_global("../lib/scope.js");
 load_global("../lib/output.js");
 load_global("../lib/compress.js");