more AST_If optimizations
This commit is contained in:
@@ -122,17 +122,17 @@ function Compressor(options, false_by_default) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
function SQUEEZE(nodetype, squeeze) {
|
function SQUEEZE(nodetype, squeeze) {
|
||||||
nodetype.DEFMETHOD("squeeze", function(compressor){
|
nodetype.DEFMETHOD("squeeze", function(compressor, block, index){
|
||||||
compressor.push_node(this);
|
compressor.push_node(this);
|
||||||
var new_node = squeeze(this, compressor);
|
var new_node = squeeze(this, compressor, block, index);
|
||||||
compressor.pop_node();
|
compressor.pop_node();
|
||||||
return new_node !== undefined ? new_node : this;
|
return new_node !== undefined ? new_node : this;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
function do_list(array, compressor, splice_blocks) {
|
function do_list(array, compressor, splice_blocks) {
|
||||||
return MAP(array, function(node){
|
return MAP(array, function(node, i){
|
||||||
node = node.squeeze(compressor);
|
node = node.squeeze(compressor, array, i);
|
||||||
if (splice_blocks) {
|
if (splice_blocks) {
|
||||||
if (node instanceof AST_BlockStatement) {
|
if (node instanceof AST_BlockStatement) {
|
||||||
return MAP.splice(eliminate_spurious_blocks(node.body));
|
return MAP.splice(eliminate_spurious_blocks(node.body));
|
||||||
@@ -222,7 +222,8 @@ function Compressor(options, false_by_default) {
|
|||||||
}
|
}
|
||||||
else if (i == last
|
else if (i == last
|
||||||
&& cur instanceof AST_Exit && cur.value
|
&& cur instanceof AST_Exit && cur.value
|
||||||
&& a.length == 1 && prev instanceof AST_SimpleStatement) {
|
&& a.length > 0
|
||||||
|
&& prev instanceof AST_SimpleStatement) {
|
||||||
// it only makes sense to do this transformation
|
// it only makes sense to do this transformation
|
||||||
// if the AST gets to a single statement.
|
// if the AST gets to a single statement.
|
||||||
var seq = make_node(AST_Seq, prev, {
|
var seq = make_node(AST_Seq, prev, {
|
||||||
@@ -230,7 +231,9 @@ function Compressor(options, false_by_default) {
|
|||||||
second: cur.value
|
second: cur.value
|
||||||
});
|
});
|
||||||
cur.value = seq;
|
cur.value = seq;
|
||||||
return [ cur ];
|
a.pop();
|
||||||
|
a.push(cur);
|
||||||
|
return a;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
a.push(cur);
|
a.push(cur);
|
||||||
@@ -459,7 +462,9 @@ function Compressor(options, false_by_default) {
|
|||||||
return basic_negation(this);
|
return basic_negation(this);
|
||||||
});
|
});
|
||||||
})(function(node, func){
|
})(function(node, func){
|
||||||
node.DEFMETHOD("negate", func);
|
node.DEFMETHOD("negate", function(compressor){
|
||||||
|
return func.call(this, compressor).optimize(compressor);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// determine if expression has side effects
|
// determine if expression has side effects
|
||||||
@@ -494,6 +499,15 @@ function Compressor(options, false_by_default) {
|
|||||||
node.DEFMETHOD("has_side_effects", func);
|
node.DEFMETHOD("has_side_effects", func);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// tell me if a statement aborts
|
||||||
|
(function(def){
|
||||||
|
def(AST_StatementBase, function(){ return null });
|
||||||
|
def(AST_Jump, function(){ return this });
|
||||||
|
def(AST_BlockStatement, function(){ return this.body[this.body.length - 1].aborts() });
|
||||||
|
})(function(node, func){
|
||||||
|
node.DEFMETHOD("aborts", func);
|
||||||
|
});
|
||||||
|
|
||||||
/* -----[ node squeezers ]----- */
|
/* -----[ node squeezers ]----- */
|
||||||
|
|
||||||
SQUEEZE(AST_Debugger, function(self, compressor){
|
SQUEEZE(AST_Debugger, function(self, compressor){
|
||||||
@@ -516,9 +530,13 @@ function Compressor(options, false_by_default) {
|
|||||||
SQUEEZE(AST_BlockStatement, function(self, compressor){
|
SQUEEZE(AST_BlockStatement, function(self, compressor){
|
||||||
self = self.clone();
|
self = self.clone();
|
||||||
self.body = tighten_body(self.body, compressor);
|
self.body = tighten_body(self.body, compressor);
|
||||||
if (self.body.length == 1)
|
return self.optimize(compressor);
|
||||||
return self.body[0];
|
});
|
||||||
return self;
|
|
||||||
|
AST_BlockStatement.DEFMETHOD("optimize", function(compressor){
|
||||||
|
if (this.body.length == 1)
|
||||||
|
return this.body[0];
|
||||||
|
return this;
|
||||||
});
|
});
|
||||||
|
|
||||||
SQUEEZE(AST_Block, function(self, compressor){
|
SQUEEZE(AST_Block, function(self, compressor){
|
||||||
@@ -705,16 +723,16 @@ function Compressor(options, false_by_default) {
|
|||||||
return self;
|
return self;
|
||||||
});
|
});
|
||||||
|
|
||||||
SQUEEZE(AST_If, function(self, compressor){
|
SQUEEZE(AST_If, function(self, compressor, block, index){
|
||||||
self = self.clone();
|
self = self.clone();
|
||||||
self.condition = self.condition.squeeze(compressor);
|
self.condition = self.condition.squeeze(compressor);
|
||||||
self.body = self.body.squeeze(compressor);
|
self.body = self.body.squeeze(compressor);
|
||||||
if (self.alternative)
|
if (self.alternative)
|
||||||
self.alternative = self.alternative.squeeze(compressor);
|
self.alternative = self.alternative.squeeze(compressor);
|
||||||
return self.optimize(compressor);
|
return self.optimize(compressor, block, index);
|
||||||
});
|
});
|
||||||
|
|
||||||
AST_If.DEFMETHOD("optimize", function(compressor){
|
AST_If.DEFMETHOD("optimize", function(compressor, block, index){
|
||||||
var self = this;
|
var self = this;
|
||||||
if (!compressor.option("conditionals")) return self;
|
if (!compressor.option("conditionals")) return self;
|
||||||
// if condition can be statically determined, warn and drop
|
// if condition can be statically determined, warn and drop
|
||||||
@@ -809,6 +827,49 @@ function Compressor(options, false_by_default) {
|
|||||||
}).optimize(compressor)
|
}).optimize(compressor)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
if (self.body instanceof AST_Return
|
||||||
|
&& !self.body.value
|
||||||
|
&& !self.alternative
|
||||||
|
&& index < block.length - 1) {
|
||||||
|
if (compressor.parent() instanceof AST_Lambda) {
|
||||||
|
var rest = tighten_body(block.slice(index + 1), compressor);
|
||||||
|
var cond = negated_is_best ? negated : self.condition.negate(compressor);
|
||||||
|
while (rest[0] instanceof AST_If && rest[0].body instanceof AST_Return && !rest[0].alternative) {
|
||||||
|
cond = make_node(AST_Binary, rest[0], {
|
||||||
|
operator: "&&",
|
||||||
|
left: cond,
|
||||||
|
right: rest[0].condition.negate(compressor)
|
||||||
|
});
|
||||||
|
rest.shift();
|
||||||
|
}
|
||||||
|
return MAP.last(make_node(AST_If, self, {
|
||||||
|
condition: cond,
|
||||||
|
body: make_node(AST_BlockStatement, block[index + 1], {
|
||||||
|
body: rest
|
||||||
|
}).optimize(compressor)
|
||||||
|
}).optimize(compressor));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (self.body instanceof AST_If
|
||||||
|
&& !self.body.alternative
|
||||||
|
&& !self.alternative) {
|
||||||
|
self.condition = make_node(AST_Binary, self.condition, {
|
||||||
|
operator: "&&",
|
||||||
|
left: self.condition,
|
||||||
|
right: self.body.condition
|
||||||
|
});
|
||||||
|
self.body = self.body.body;
|
||||||
|
}
|
||||||
|
var abort = self.body.aborts();
|
||||||
|
if (abort) {
|
||||||
|
if (self.alternative) {
|
||||||
|
var alt = self.alternative;
|
||||||
|
self.alternative = null;
|
||||||
|
return make_node(AST_BlockStatement, self, {
|
||||||
|
body: [ self, alt ]
|
||||||
|
}).optimize(compressor);
|
||||||
|
}
|
||||||
|
}
|
||||||
return self;
|
return self;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
13
lib/utils.js
13
lib/utils.js
@@ -113,6 +113,8 @@ var MAP = (function(){
|
|||||||
var ret = [], top = [], i;
|
var ret = [], top = [], i;
|
||||||
function doit() {
|
function doit() {
|
||||||
var val = f.call(o, a[i], i);
|
var val = f.call(o, a[i], i);
|
||||||
|
var is_last = val instanceof Last;
|
||||||
|
if (is_last) val = val.v;
|
||||||
if (val instanceof AtTop) {
|
if (val instanceof AtTop) {
|
||||||
val = val.v;
|
val = val.v;
|
||||||
if (val instanceof Splice) {
|
if (val instanceof Splice) {
|
||||||
@@ -128,16 +130,23 @@ var MAP = (function(){
|
|||||||
ret.push(val);
|
ret.push(val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return is_last;
|
||||||
};
|
};
|
||||||
if (a instanceof Array) for (i = 0; i < a.length; ++i) doit();
|
if (a instanceof Array) {
|
||||||
else for (i in a) if (HOP(a, i)) doit();
|
for (i = 0; i < a.length; ++i) if (doit()) break;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for (i in a) if (HOP(a, i)) if (doit()) break;
|
||||||
|
}
|
||||||
return top.concat(ret);
|
return top.concat(ret);
|
||||||
};
|
};
|
||||||
MAP.at_top = function(val) { return new AtTop(val) };
|
MAP.at_top = function(val) { return new AtTop(val) };
|
||||||
MAP.splice = function(val) { return new Splice(val) };
|
MAP.splice = function(val) { return new Splice(val) };
|
||||||
|
MAP.last = function(val) { return new Last(val) };
|
||||||
var skip = MAP.skip = {};
|
var skip = MAP.skip = {};
|
||||||
function AtTop(val) { this.v = val };
|
function AtTop(val) { this.v = val };
|
||||||
function Splice(val) { this.v = val };
|
function Splice(val) { this.v = val };
|
||||||
|
function Last(val) { this.v = val };
|
||||||
return MAP;
|
return MAP;
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user