[WIP] improve compression of undefined, NaN & Infinitiy
Maintains identical behaviour, but move all the transformation logic from `OutputStream` to `Compressor`.
This commit is contained in:
parent
1ddc05725d
commit
da0273e805
|
|
@ -215,7 +215,12 @@ merge(Compressor.prototype, {
|
||||||
}) : make_node(AST_EmptyStatement, node);
|
}) : make_node(AST_EmptyStatement, node);
|
||||||
}
|
}
|
||||||
return make_node(AST_SimpleStatement, node, {
|
return make_node(AST_SimpleStatement, node, {
|
||||||
body: node.value || make_node(AST_Undefined, node)
|
body: node.value || make_node(AST_UnaryPrefix, node, {
|
||||||
|
operator: "void",
|
||||||
|
expression: make_node(AST_Number, node, {
|
||||||
|
value: 0
|
||||||
|
})
|
||||||
|
})
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (node instanceof AST_Lambda && node !== self) {
|
if (node instanceof AST_Lambda && node !== self) {
|
||||||
|
|
@ -1123,8 +1128,12 @@ merge(Compressor.prototype, {
|
||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
|
|
||||||
function is_undefined(node) {
|
function is_undefined(node, compressor) {
|
||||||
return node instanceof AST_Undefined || node.is_undefined;
|
return node.is_undefined
|
||||||
|
|| node instanceof AST_Undefined
|
||||||
|
|| node instanceof AST_UnaryPrefix
|
||||||
|
&& node.operator == "void"
|
||||||
|
&& !node.expression.has_side_effects(compressor);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -----[ boolean/negation helpers ]----- */
|
/* -----[ boolean/negation helpers ]----- */
|
||||||
|
|
@ -1313,7 +1322,7 @@ merge(Compressor.prototype, {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
var unaryPrefix = makePredicate("! ~ - +");
|
var unaryPrefix = makePredicate("! ~ - + void");
|
||||||
AST_Node.DEFMETHOD("is_constant", function(){
|
AST_Node.DEFMETHOD("is_constant", function(){
|
||||||
// Accomodate when compress option evaluate=false
|
// Accomodate when compress option evaluate=false
|
||||||
// as well as the common constant expressions !0 and -1
|
// as well as the common constant expressions !0 and -1
|
||||||
|
|
@ -2971,7 +2980,7 @@ merge(Compressor.prototype, {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (is_undefined(self.cdr)) {
|
if (is_undefined(self.cdr, compressor)) {
|
||||||
return make_node(AST_UnaryPrefix, self, {
|
return make_node(AST_UnaryPrefix, self, {
|
||||||
operator : "void",
|
operator : "void",
|
||||||
expression : self.car
|
expression : self.car
|
||||||
|
|
@ -3010,7 +3019,7 @@ merge(Compressor.prototype, {
|
||||||
self.expression = e;
|
self.expression = e;
|
||||||
return self;
|
return self;
|
||||||
} else {
|
} else {
|
||||||
return make_node(AST_Undefined, self).transform(compressor);
|
return make_node(AST_Undefined, self).optimize(compressor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (compressor.option("booleans") && compressor.in_boolean_context()) {
|
if (compressor.option("booleans") && compressor.in_boolean_context()) {
|
||||||
|
|
@ -3034,6 +3043,9 @@ merge(Compressor.prototype, {
|
||||||
})).optimize(compressor);
|
})).optimize(compressor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (self.operator == "-" && e instanceof AST_Infinity) {
|
||||||
|
e = e.transform(compressor);
|
||||||
|
}
|
||||||
if (e instanceof AST_Binary
|
if (e instanceof AST_Binary
|
||||||
&& (self.operator == "+" || self.operator == "-")
|
&& (self.operator == "+" || self.operator == "-")
|
||||||
&& (e.operator == "*" || e.operator == "/" || e.operator == "%")) {
|
&& (e.operator == "*" || e.operator == "/" || e.operator == "%")) {
|
||||||
|
|
@ -3043,8 +3055,7 @@ merge(Compressor.prototype, {
|
||||||
}
|
}
|
||||||
// avoids infinite recursion of numerals
|
// avoids infinite recursion of numerals
|
||||||
if (self.operator != "-"
|
if (self.operator != "-"
|
||||||
|| !(self.expression instanceof AST_Number
|
|| !(e instanceof AST_Number || e instanceof AST_Infinity)) {
|
||||||
|| self.expression instanceof AST_Infinity)) {
|
|
||||||
var ev = self.evaluate(compressor);
|
var ev = self.evaluate(compressor);
|
||||||
if (ev !== self) {
|
if (ev !== self) {
|
||||||
ev = make_node_from_constant(ev, self).optimize(compressor);
|
ev = make_node_from_constant(ev, self).optimize(compressor);
|
||||||
|
|
@ -3087,8 +3098,8 @@ merge(Compressor.prototype, {
|
||||||
|
|
||||||
OPT(AST_Binary, function(self, compressor){
|
OPT(AST_Binary, function(self, compressor){
|
||||||
function reversible() {
|
function reversible() {
|
||||||
return self.left instanceof AST_Constant
|
return self.left.is_constant()
|
||||||
|| self.right instanceof AST_Constant
|
|| self.right.is_constant()
|
||||||
|| !self.left.has_side_effects(compressor)
|
|| !self.left.has_side_effects(compressor)
|
||||||
&& !self.right.has_side_effects(compressor);
|
&& !self.right.has_side_effects(compressor);
|
||||||
}
|
}
|
||||||
|
|
@ -3101,8 +3112,8 @@ merge(Compressor.prototype, {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (commutativeOperators(self.operator)) {
|
if (commutativeOperators(self.operator)) {
|
||||||
if (self.right instanceof AST_Constant
|
if (self.right.is_constant()
|
||||||
&& !(self.left instanceof AST_Constant)) {
|
&& !self.left.is_constant()) {
|
||||||
// if right is a constant, whatever side effects the
|
// if right is a constant, whatever side effects the
|
||||||
// left side might have could not influence the
|
// left side might have could not influence the
|
||||||
// result. hence, force switch.
|
// result. hence, force switch.
|
||||||
|
|
@ -3464,9 +3475,9 @@ merge(Compressor.prototype, {
|
||||||
case "undefined":
|
case "undefined":
|
||||||
return make_node(AST_Undefined, self).optimize(compressor);
|
return make_node(AST_Undefined, self).optimize(compressor);
|
||||||
case "NaN":
|
case "NaN":
|
||||||
return make_node(AST_NaN, self);
|
return make_node(AST_NaN, self).optimize(compressor);
|
||||||
case "Infinity":
|
case "Infinity":
|
||||||
return make_node(AST_Infinity, self);
|
return make_node(AST_Infinity, self).optimize(compressor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (compressor.option("evaluate") && compressor.option("reduce_vars")) {
|
if (compressor.option("evaluate") && compressor.option("reduce_vars")) {
|
||||||
|
|
@ -3508,7 +3519,36 @@ merge(Compressor.prototype, {
|
||||||
return ref;
|
return ref;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return self;
|
return make_node(AST_UnaryPrefix, self, {
|
||||||
|
operator: "void",
|
||||||
|
expression: make_node(AST_Number, self, {
|
||||||
|
value: 0
|
||||||
|
})
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
OPT(AST_Infinity, function(self, compressor){
|
||||||
|
return make_node(AST_Binary, self, {
|
||||||
|
operator: "/",
|
||||||
|
left: make_node(AST_Number, self, {
|
||||||
|
value: 1
|
||||||
|
}),
|
||||||
|
right: make_node(AST_Number, self, {
|
||||||
|
value: 0
|
||||||
|
})
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
OPT(AST_NaN, function(self, compressor){
|
||||||
|
return make_node(AST_Binary, self, {
|
||||||
|
operator: "/",
|
||||||
|
left: make_node(AST_Number, self, {
|
||||||
|
value: 0
|
||||||
|
}),
|
||||||
|
right: make_node(AST_Number, self, {
|
||||||
|
value: 0
|
||||||
|
})
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
var ASSIGN_OPS = [ '+', '-', '/', '*', '%', '>>', '<<', '>>>', '|', '^', '&' ];
|
var ASSIGN_OPS = [ '+', '-', '/', '*', '%', '>>', '<<', '>>>', '|', '^', '&' ];
|
||||||
|
|
@ -3809,7 +3849,7 @@ merge(Compressor.prototype, {
|
||||||
OPT(AST_RegExp, literals_in_boolean_context);
|
OPT(AST_RegExp, literals_in_boolean_context);
|
||||||
|
|
||||||
OPT(AST_Return, function(self, compressor){
|
OPT(AST_Return, function(self, compressor){
|
||||||
if (self.value && is_undefined(self.value)) {
|
if (self.value && is_undefined(self.value, compressor)) {
|
||||||
self.value = null;
|
self.value = null;
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
|
|
|
||||||
|
|
@ -586,21 +586,12 @@ function OutputStream(options) {
|
||||||
return first_in_statement(output);
|
return first_in_statement(output);
|
||||||
});
|
});
|
||||||
|
|
||||||
PARENS([ AST_Unary, AST_Undefined ], function(output){
|
PARENS(AST_Unary, function(output){
|
||||||
var p = output.parent();
|
var p = output.parent();
|
||||||
return p instanceof AST_PropAccess && p.expression === this
|
return p instanceof AST_PropAccess && p.expression === this
|
||||||
|| p instanceof AST_Call && p.expression === this;
|
|| p instanceof AST_Call && p.expression === this;
|
||||||
});
|
});
|
||||||
|
|
||||||
PARENS([ AST_Infinity, AST_NaN ], function(output){
|
|
||||||
var p = output.parent();
|
|
||||||
return p instanceof AST_PropAccess && p.expression === this
|
|
||||||
|| p instanceof AST_Call && p.expression === this
|
|
||||||
|| p instanceof AST_Unary && p.operator != "+" && p.operator != "-"
|
|
||||||
|| p instanceof AST_Binary && p.right === this
|
|
||||||
&& (p.operator == "/" || p.operator == "%");
|
|
||||||
});
|
|
||||||
|
|
||||||
PARENS(AST_Seq, function(output){
|
PARENS(AST_Seq, function(output){
|
||||||
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)
|
||||||
|
|
@ -1258,24 +1249,7 @@ function OutputStream(options) {
|
||||||
var def = self.definition();
|
var def = self.definition();
|
||||||
output.print_name(def ? def.mangled_name || def.name : self.name);
|
output.print_name(def ? def.mangled_name || def.name : self.name);
|
||||||
});
|
});
|
||||||
DEFPRINT(AST_Undefined, function(self, output){
|
|
||||||
output.print("void 0");
|
|
||||||
});
|
|
||||||
DEFPRINT(AST_Hole, noop);
|
DEFPRINT(AST_Hole, noop);
|
||||||
DEFPRINT(AST_Infinity, function(self, output){
|
|
||||||
output.print("1");
|
|
||||||
output.space();
|
|
||||||
output.print("/");
|
|
||||||
output.space();
|
|
||||||
output.print("0");
|
|
||||||
});
|
|
||||||
DEFPRINT(AST_NaN, function(self, output){
|
|
||||||
output.print("0");
|
|
||||||
output.space();
|
|
||||||
output.print("/");
|
|
||||||
output.space();
|
|
||||||
output.print("0");
|
|
||||||
});
|
|
||||||
DEFPRINT(AST_This, function(self, output){
|
DEFPRINT(AST_This, function(self, output){
|
||||||
output.print("this");
|
output.print("this");
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user