more sequence optimizations (lift some sequences above binary/unary expressions so that we can avoid parens)

This commit is contained in:
Mihai Bazon
2012-10-22 11:49:58 +03:00
parent 41be8632d3
commit 30faaf13ed
4 changed files with 102 additions and 1 deletions

View File

@@ -581,6 +581,18 @@ var AST_Seq = DEFNODE("Seq", "car cdr", {
} }
return list; return list;
}, },
to_array: function() {
var p = this, a = [];
while (p) {
a.push(p.car);
if (p.cdr && !(p.cdr instanceof AST_Seq)) {
a.push(p.cdr);
break;
}
p = p.cdr;
}
return a;
},
add: function(node) { add: function(node) {
var p = this; var p = this;
while (p) { while (p) {

View File

@@ -1380,6 +1380,10 @@ merge(Compressor.prototype, {
}); });
OPT(AST_Seq, function(self, compressor){ OPT(AST_Seq, function(self, compressor){
if (!compressor.option("side_effects"))
return self;
if (!self.car.has_side_effects())
return self.cdr;
if (compressor.option("cascade")) { if (compressor.option("cascade")) {
if (self.car instanceof AST_Assign if (self.car instanceof AST_Assign
&& !self.car.left.has_side_effects() && !self.car.left.has_side_effects()
@@ -1395,7 +1399,26 @@ merge(Compressor.prototype, {
return self; return self;
}); });
AST_Unary.DEFMETHOD("lift_sequences", function(compressor){
if (compressor.option("sequences")) {
if (this.expression instanceof 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);
return seq;
}
}
return this;
});
OPT(AST_UnaryPostfix, function(self, compressor){
return self.lift_sequences(compressor);
});
OPT(AST_UnaryPrefix, function(self, compressor){ OPT(AST_UnaryPrefix, function(self, compressor){
self = self.lift_sequences(compressor);
var e = self.expression; var e = self.expression;
if (compressor.option("booleans") && compressor.in_boolean_context()) { if (compressor.option("booleans") && compressor.in_boolean_context()) {
switch (self.operator) { switch (self.operator) {
@@ -1418,7 +1441,32 @@ merge(Compressor.prototype, {
return self.evaluate(compressor)[0]; return self.evaluate(compressor)[0];
}); });
AST_Binary.DEFMETHOD("lift_sequences", function(compressor){
if (compressor.option("sequences")) {
if (this.left instanceof 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);
return seq;
}
if (this.right instanceof AST_Seq
&& !(this.operator == "||" || this.operator == "&&")
&& !this.left.has_side_effects()) {
var seq = this.right;
var x = seq.to_array();
this.right = x.pop();
x.push(this);
seq = AST_Seq.from_array(x).transform(compressor);
return seq;
}
}
return this;
});
OPT(AST_Binary, function(self, compressor){ OPT(AST_Binary, function(self, compressor){
self = self.lift_sequences(compressor);
if (compressor.option("comparisons")) switch (self.operator) { if (compressor.option("comparisons")) switch (self.operator) {
case "===": case "===":
case "!==": case "!==":
@@ -1557,6 +1605,7 @@ merge(Compressor.prototype, {
var ASSIGN_OPS = [ '+', '-', '/', '*', '%', '>>', '<<', '>>>', '|', '^', '&' ]; var ASSIGN_OPS = [ '+', '-', '/', '*', '%', '>>', '<<', '>>>', '|', '^', '&' ];
OPT(AST_Assign, function(self, compressor){ OPT(AST_Assign, function(self, compressor){
self = self.lift_sequences(compressor);
if (self.operator == "=" if (self.operator == "="
&& self.left instanceof AST_SymbolRef && self.left instanceof AST_SymbolRef
&& self.right instanceof AST_Binary && self.right instanceof AST_Binary

View File

@@ -414,7 +414,7 @@ function OutputStream(options) {
var p = output.parent(); var p = output.parent();
return p instanceof AST_Call // (foo, bar)() or foo(1, (2, 3), 4) return p instanceof AST_Call // (foo, bar)() or foo(1, (2, 3), 4)
|| p instanceof AST_Unary // !(foo, bar, baz) || p instanceof AST_Unary // !(foo, bar, baz)
|| p instanceof AST_Binary // 1 + (2, 3) + 4 ==> 7 || 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_VarDef // var a = (1, 2), b = a + a; ==> b == 4
|| p instanceof AST_Dot // (1, {foo:2}).foo ==> 2 || p instanceof AST_Dot // (1, {foo:2}).foo ==> 2
|| p instanceof AST_Array // [ 1, (2, 3), 4 ] ==> [ 1, 3, 4 ] || p instanceof AST_Array // [ 1, (2, 3), 4 ] ==> [ 1, 3, 4 ]

View File

@@ -87,3 +87,43 @@ make_sequences_4: {
with (x = 5, obj); with (x = 5, obj);
} }
} }
lift_sequences_1: {
options = { sequences: true };
input: {
foo = !(x(), y(), bar());
}
expect: {
x(), y(), foo = !bar();
}
}
lift_sequences_2: {
options = { sequences: true, evaluate: true };
input: {
q = 1 + (foo(), bar(), 5) + 7 * (5 / (3 - (a(), (QW=ER), c(), 2))) - (x(), y(), 5);
}
expect: {
foo(), bar(), a(), QW = ER, c(), x(), y(), q = 36
}
}
lift_sequences_3: {
options = { sequences: true, conditionals: true };
input: {
x = (foo(), bar(), baz()) ? 10 : 20;
}
expect: {
foo(), bar(), x = baz() ? 10 : 20;
}
}
lift_sequences_4: {
options = { side_effects: true };
input: {
x = (foo, bar, baz);
}
expect: {
x = baz;
}
}