wrote more of the compressor and added some tests
This commit is contained in:
149
lib/compress.js
149
lib/compress.js
@@ -9,13 +9,16 @@
|
||||
// maintaining various internal state that might be useful for
|
||||
// squeezing nodes.
|
||||
|
||||
function Compressor(options) {
|
||||
function Compressor(options, false_by_default) {
|
||||
options = defaults(options, {
|
||||
sequences : true,
|
||||
dead_code : true,
|
||||
keep_comps : true,
|
||||
drop_debugger : true,
|
||||
unsafe : true
|
||||
sequences : !false_by_default,
|
||||
properties : !false_by_default,
|
||||
dead_code : !false_by_default,
|
||||
keep_comps : !false_by_default,
|
||||
drop_debugger : !false_by_default,
|
||||
unsafe : !false_by_default,
|
||||
|
||||
warnings : true
|
||||
});
|
||||
var stack = [];
|
||||
return {
|
||||
@@ -25,6 +28,10 @@ function Compressor(options) {
|
||||
stack : function() { return stack },
|
||||
parent : function(n) {
|
||||
return stack[stack.length - 2 - (n || 0)];
|
||||
},
|
||||
warn : function() {
|
||||
if (options.warnings)
|
||||
AST_Node.warn.apply(AST_Node, arguments);
|
||||
}
|
||||
};
|
||||
};
|
||||
@@ -35,6 +42,12 @@ function Compressor(options) {
|
||||
return this;
|
||||
});
|
||||
|
||||
function make_node(ctor, orig, props) {
|
||||
if (!props.start) props.start = orig.start;
|
||||
if (!props.end) props.end = orig.end;
|
||||
return new ctor(props);
|
||||
};
|
||||
|
||||
function SQUEEZE(nodetype, squeeze) {
|
||||
nodetype.DEFMETHOD("squeeze", function(compressor){
|
||||
compressor.push_node(this);
|
||||
@@ -46,11 +59,6 @@ function Compressor(options) {
|
||||
|
||||
function do_list(array, compressor) {
|
||||
return MAP(array, function(node){
|
||||
if (node instanceof Array) {
|
||||
sys.debug(node.map(function(node){
|
||||
return node.TYPE;
|
||||
}).join("\n"));
|
||||
}
|
||||
return node.squeeze(compressor);
|
||||
});
|
||||
};
|
||||
@@ -72,15 +80,109 @@ function Compressor(options) {
|
||||
return self;
|
||||
});
|
||||
|
||||
function tighten_body(statements, compressor) {
|
||||
statements = do_list(statements, compressor);
|
||||
statements = eliminate_spurious_blocks(statements);
|
||||
if (compressor.option("dead_code")) {
|
||||
statements = eliminate_dead_code(statements, compressor);
|
||||
}
|
||||
if (compressor.option("sequences")) {
|
||||
statements = sequencesize(statements);
|
||||
}
|
||||
return statements;
|
||||
};
|
||||
|
||||
function eliminate_spurious_blocks(statements) {
|
||||
return statements.reduce(function(a, stat){
|
||||
if (stat.TYPE == "BlockStatement") {
|
||||
// XXX: no instanceof here because we would catch
|
||||
// AST_Lambda-s and other blocks too. perhaps we
|
||||
// should refine the hierarchy.
|
||||
a.push.apply(a, stat.body);
|
||||
} else {
|
||||
a.push(stat);
|
||||
}
|
||||
return a;
|
||||
}, []);
|
||||
}
|
||||
|
||||
function eliminate_dead_code(statements, compressor) {
|
||||
var has_quit = false;
|
||||
return statements.reduce(function(a, stat){
|
||||
if (has_quit) {
|
||||
if (stat instanceof AST_Defun) {
|
||||
a.push(stat);
|
||||
}
|
||||
else if (compressor.option("warnings")) {
|
||||
stat.walk(new TreeWalker(function(node){
|
||||
if (node instanceof AST_Definitions
|
||||
|| node instanceof AST_Defun) {
|
||||
compressor.warn("Declarations in unreachable code! [{line},{col}]", node.start);
|
||||
if (node instanceof AST_Definitions) {
|
||||
node = node.clone();
|
||||
node.remove_initializers();
|
||||
a.push(node);
|
||||
}
|
||||
else if (node instanceof AST_Defun) {
|
||||
a.push(node);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (node instanceof AST_Scope)
|
||||
return true;
|
||||
}))
|
||||
};
|
||||
} else {
|
||||
a.push(stat);
|
||||
if (stat instanceof AST_Jump) {
|
||||
has_quit = true;
|
||||
}
|
||||
}
|
||||
return a;
|
||||
}, []);
|
||||
}
|
||||
|
||||
function sequencesize(statements) {
|
||||
var prev = null, last = statements.length - 1;
|
||||
if (last) statements = statements.reduce(function(a, cur, i){
|
||||
if (prev instanceof AST_SimpleStatement
|
||||
&& cur instanceof AST_SimpleStatement) {
|
||||
var seq = make_node(AST_Seq, prev, {
|
||||
first: prev.body,
|
||||
second: cur.body
|
||||
});
|
||||
prev.body = seq;
|
||||
}
|
||||
else if (i == last && cur instanceof AST_Exit
|
||||
&& cur.value && a.length == 1) {
|
||||
// it only makes sense to do this transformation
|
||||
// if the AST gets to a single statement.
|
||||
var seq = make_node(AST_Seq, prev, {
|
||||
first: prev.body,
|
||||
second: cur.value
|
||||
});
|
||||
cur.value = seq;
|
||||
return [ cur ];
|
||||
}
|
||||
else {
|
||||
a.push(cur);
|
||||
prev = cur;
|
||||
}
|
||||
return a;
|
||||
}, []);
|
||||
return statements;
|
||||
}
|
||||
|
||||
SQUEEZE(AST_BlockStatement, function(self, compressor){
|
||||
self = self.clone();
|
||||
self.body = do_list(self.body, compressor);
|
||||
self.body = tighten_body(self.body, compressor);
|
||||
if (self.body.length == 1 && !self.required)
|
||||
return self.body[0];
|
||||
return self;
|
||||
});
|
||||
|
||||
SQUEEZE(AST_EmptyStatement, function(self, compressor){
|
||||
if (compressor.parent() instanceof AST_BlockStatement)
|
||||
return MAP.skip;
|
||||
return self;
|
||||
});
|
||||
|
||||
SQUEEZE(AST_DWLoop, function(self, compressor){
|
||||
@@ -144,7 +246,7 @@ function Compressor(options) {
|
||||
SQUEEZE(AST_Case, function(self, compressor){
|
||||
self = self.clone();
|
||||
self.expression = self.expression.squeeze(compressor);
|
||||
self.body = do_list(self.body, compressor);
|
||||
self.body = tighten_body(self.body, compressor);
|
||||
return self;
|
||||
});
|
||||
|
||||
@@ -156,6 +258,14 @@ function Compressor(options) {
|
||||
return self;
|
||||
});
|
||||
|
||||
AST_Definitions.DEFMETHOD("remove_initializers", function(){
|
||||
this.definitions = this.definitions.map(function(def){
|
||||
var def = def.clone();
|
||||
def.value = null;
|
||||
return def;
|
||||
});
|
||||
});
|
||||
|
||||
SQUEEZE(AST_Definitions, function(self, compressor){
|
||||
self = self.clone();
|
||||
self.definitions = do_list(self.definitions, compressor);
|
||||
@@ -199,7 +309,14 @@ function Compressor(options) {
|
||||
SQUEEZE(AST_Sub, function(self, compressor){
|
||||
self = self.clone();
|
||||
self.expression = self.expression.squeeze(compressor);
|
||||
self.property = self.property.squeeze(compressor);
|
||||
var prop = self.property = self.property.squeeze(compressor);
|
||||
if (prop instanceof AST_String && compressor.option("properties")) {
|
||||
prop = prop.getValue();
|
||||
if (is_identifier(prop)) {
|
||||
self = new AST_Dot(self);
|
||||
self.property = prop;
|
||||
}
|
||||
}
|
||||
return self;
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user