compress arithmetic expressions further (#3529)

This commit is contained in:
Alex Lam S.L
2019-10-27 03:07:07 +08:00
committed by GitHub
parent 85237b08d4
commit 50a578c1f6
3 changed files with 433 additions and 76 deletions

View File

@@ -2437,9 +2437,10 @@ merge(Compressor.prototype, {
|| this.operator == "=" && this.right.is_number(compressor);
});
def(AST_Binary, function(compressor) {
return binary[this.operator] || this.operator == "+"
&& this.left.is_number(compressor)
&& this.right.is_number(compressor);
if (binary[this.operator]) return true;
if (this.operator != "+") return false;
return (this.left.is_boolean(compressor) || this.left.is_number(compressor))
&& (this.right.is_boolean(compressor) || this.right.is_number(compressor));
});
var fn = makePredicate([
"charCodeAt",
@@ -5777,6 +5778,7 @@ merge(Compressor.prototype, {
}
}
if (compressor.option("evaluate")) {
var associative = true;
switch (self.operator) {
case "&&":
var ll = fuzzy_eval(self.left);
@@ -5845,9 +5847,6 @@ merge(Compressor.prototype, {
}).optimize(compressor);
}
break;
}
var associative = true;
switch (self.operator) {
case "+":
// "foo" + ("bar" + x) => "foobar" + x
if (self.left instanceof AST_Constant
@@ -5927,13 +5926,38 @@ merge(Compressor.prototype, {
});
break;
}
case "-":
// a - -b => a + b
if (self.right instanceof AST_UnaryPrefix
&& self.right.operator == "-"
&& self.left.is_number(compressor)) {
self = make_node(AST_Binary, self, {
operator: "+",
left: self.left,
right: self.right.expression
});
break;
}
case "*":
case "/":
associative = compressor.option("unsafe_math");
// +a - b => a - b
// a - +b => a - b
if (self.operator != "+") {
if (self.left instanceof AST_UnaryPrefix && self.left.operator == "+") {
self.left = self.left.expression;
}
if (self.right instanceof AST_UnaryPrefix && self.right.operator == "+") {
self.right = self.right.expression;
}
}
case "&":
case "|":
case "^":
// a + +b => +b + a
if (self.left.is_number(compressor)
if (self.operator != "-"
&& self.operator != "/"
&& self.left.is_number(compressor)
&& self.right.is_number(compressor)
&& reversible()
&& !(self.left instanceof AST_Binary
@@ -5951,77 +5975,56 @@ merge(Compressor.prototype, {
self = best_of(compressor, self, reversed);
}
}
if (associative && self.is_number(compressor)) {
// a + (b + c) => (a + b) + c
if (self.right instanceof AST_Binary
&& self.right.operator == self.operator) {
self = make_node(AST_Binary, self, {
if (!associative || !self.is_number(compressor)) break;
// a + (b + c) => (a + b) + c
if (self.right instanceof AST_Binary
&& self.right.operator != "%"
&& PRECEDENCE[self.right.operator] == PRECEDENCE[self.operator]) {
self = make_node(AST_Binary, self, {
operator: align(self.operator, self.right.operator),
left: make_node(AST_Binary, self.left, {
operator: self.operator,
left: self.left,
right: self.right.left,
start: self.left.start,
end: self.right.left.end
}),
right: self.right.right
});
}
// (2 * n) * 3 => 6 * n
// (n + 2) + 3 => n + 5
if (self.right instanceof AST_Constant
&& self.left instanceof AST_Binary
&& self.left.operator != "%"
&& PRECEDENCE[self.left.operator] == PRECEDENCE[self.operator]) {
if (self.left.left instanceof AST_Constant) {
self = make_node(AST_Binary, self, {
operator: self.left.operator,
left: make_node(AST_Binary, self.left, {
operator: self.operator,
left: self.left,
right: self.right.left,
start: self.left.start,
end: self.right.left.end
left: self.left.left,
right: self.right,
start: self.left.left.start,
end: self.right.end
}),
right: self.right.right
right: self.left.right
});
}
// (n + 2) + 3 => 5 + n
// (2 * n) * 3 => 6 + n
if (self.right instanceof AST_Constant
&& self.left instanceof AST_Binary
&& self.left.operator == self.operator) {
if (self.left.left instanceof AST_Constant) {
self = make_node(AST_Binary, self, {
operator: self.operator,
left: make_node(AST_Binary, self.left, {
operator: self.operator,
left: self.left.left,
right: self.right,
start: self.left.left.start,
end: self.right.end
}),
right: self.left.right
});
} else if (self.left.right instanceof AST_Constant) {
self = make_node(AST_Binary, self, {
operator: self.operator,
left: make_node(AST_Binary, self.left, {
operator: self.operator,
left: self.left.right,
right: self.right,
start: self.left.right.start,
end: self.right.end
}),
right: self.left.left
});
}
}
// (a | 1) | (2 | d) => (3 | a) | b
if (self.left instanceof AST_Binary
&& self.left.operator == self.operator
&& self.left.right instanceof AST_Constant
&& self.right instanceof AST_Binary
&& self.right.operator == self.operator
&& self.right.left instanceof AST_Constant) {
} else if (self.left.right instanceof AST_Constant) {
self = make_node(AST_Binary, self, {
operator: self.operator,
left: make_node(AST_Binary, self.left, {
operator: self.operator,
left: make_node(AST_Binary, self.left.left, {
operator: self.operator,
left: self.left.right,
right: self.right.left,
start: self.left.right.start,
end: self.right.left.end
}),
right: self.left.left
}),
right: self.right.right
operator: self.left.operator,
left: self.left.left,
right: make_node(AST_Binary, self.left, {
operator: align(self.left.operator, self.operator),
left: self.left.right,
right: self.right,
start: self.left.right.start,
end: self.right.end
})
});
}
}
break;
}
}
if (compressor.option("unsafe")) {
@@ -6086,6 +6089,17 @@ merge(Compressor.prototype, {
}
return self;
function align(ref, op) {
switch (ref) {
case "-":
return op == "+" ? "-" : "+";
case "/":
return op == "*" ? "/" : "*";
default:
return op;
}
}
function fuzzy_eval(node) {
if (node.truthy) return true;
if (node.falsy) return false;