Optimize ternaries with boolean consequent or alternative.

Fixes #511
This commit is contained in:
kzc
2016-04-02 00:21:13 -04:00
committed by Richard van Velzen
parent 45ddb9caeb
commit 98434258d0
2 changed files with 109 additions and 19 deletions

View File

@@ -2658,24 +2658,58 @@ merge(Compressor.prototype, {
} }
} }
// y?true:false --> !!y if (is_true(self.consequent)) {
if (is_true(consequent) && is_false(alternative)) { if (is_false(self.alternative)) {
if (self.condition.is_boolean()) { // c ? true : false ---> !!c
// boolean_expression ? true : false --> boolean_expression return booleanize(self.condition);
return self.condition;
} }
self.condition = self.condition.negate(compressor); // c ? true : x ---> !!c || x
return make_node(AST_UnaryPrefix, self.condition, { return make_node(AST_Binary, self, {
operator: "!", operator: "||",
expression: self.condition left: booleanize(self.condition),
right: self.alternative
}); });
} }
// y?false:true --> !y if (is_false(self.consequent)) {
if (is_false(consequent) && is_true(alternative)) { if (is_true(self.alternative)) {
return self.condition.negate(compressor) // c ? false : true ---> !c
return booleanize(self.condition.negate(compressor));
}
// c ? false : x ---> !c && x
return make_node(AST_Binary, self, {
operator: "&&",
left: booleanize(self.condition.negate(compressor)),
right: self.alternative
});
} }
if (is_true(self.alternative)) {
// c ? x : true ---> !c || x
return make_node(AST_Binary, self, {
operator: "||",
left: booleanize(self.condition.negate(compressor)),
right: self.consequent
});
}
if (is_false(self.alternative)) {
// c ? x : false ---> !!c && x
return make_node(AST_Binary, self, {
operator: "&&",
left: booleanize(self.condition),
right: self.consequent
});
}
return self; return self;
function booleanize(node) {
if (node.is_boolean()) return node;
// !!expression
return make_node(AST_UnaryPrefix, node, {
operator: "!",
expression: node.negate(compressor)
});
}
// AST_True or !0 // AST_True or !0
function is_true(node) { function is_true(node) {
return node instanceof AST_True return node instanceof AST_True

View File

@@ -407,8 +407,8 @@ cond_8: {
a = !condition; a = !condition;
a = !condition; a = !condition;
a = condition ? 1 : false; a = !!condition && 1;
a = condition ? 0 : true; a = !condition || 0;
a = condition ? 1 : 0; a = condition ? 1 : 0;
} }
} }
@@ -490,8 +490,8 @@ cond_8b: {
a = !condition; a = !condition;
a = !condition; a = !condition;
a = condition ? 1 : !1; a = !!condition && 1;
a = condition ? 0 : !0; a = !condition || 0;
a = condition ? 1 : 0; a = condition ? 1 : 0;
} }
} }
@@ -557,7 +557,7 @@ cond_8c: {
a = !!condition; a = !!condition;
a = !condition; a = !condition;
a = condition() ? !0 : !-3.5; a = !!condition() || !-3.5;
a = !!condition; a = !!condition;
a = !!condition; a = !!condition;
@@ -573,12 +573,68 @@ cond_8c: {
a = !condition; a = !condition;
a = !condition; a = !condition;
a = condition ? 1 : false; a = !!condition && 1;
a = condition ? 0 : true; a = !condition || 0;
a = condition ? 1 : 0; a = condition ? 1 : 0;
} }
} }
ternary_boolean_consequent: {
options = {
collapse_vars:true, sequences:true, properties:true, dead_code:true, conditionals:true,
comparisons:true, evaluate:true, booleans:true, loops:true, unused:true, hoist_funs:true,
keep_fargs:true, if_return:true, join_vars:true, cascade:true, side_effects:true
}
input: {
function f1() { return a == b ? true : x; }
function f2() { return a == b ? false : x; }
function f3() { return a < b ? !0 : x; }
function f4() { return a < b ? !1 : x; }
function f5() { return c ? !0 : x; }
function f6() { return c ? false : x; }
function f7() { return !c ? true : x; }
function f8() { return !c ? !1 : x; }
}
expect: {
function f1() { return a == b || x; }
function f2() { return a != b && x; }
function f3() { return a < b || x; }
function f4() { return !(a < b) && x; }
function f5() { return !!c || x; }
function f6() { return !c && x; }
function f7() { return !c || x; }
function f8() { return !!c && x; }
}
}
ternary_boolean_alternative: {
options = {
collapse_vars:true, sequences:true, properties:true, dead_code:true, conditionals:true,
comparisons:true, evaluate:true, booleans:true, loops:true, unused:true, hoist_funs:true,
keep_fargs:true, if_return:true, join_vars:true, cascade:true, side_effects:true
}
input: {
function f1() { return a == b ? x : true; }
function f2() { return a == b ? x : false; }
function f3() { return a < b ? x : !0; }
function f4() { return a < b ? x : !1; }
function f5() { return c ? x : true; }
function f6() { return c ? x : !1; }
function f7() { return !c ? x : !0; }
function f8() { return !c ? x : false; }
}
expect: {
function f1() { return a != b || x; }
function f2() { return a == b && x; }
function f3() { return !(a < b) || x; }
function f4() { return a < b && x; }
function f5() { return !c || x; }
function f6() { return !!c && x; }
function f7() { return !!c || x; }
function f8() { return !c && x; }
}
}
conditional_and: { conditional_and: {
options = { options = {
conditionals: true, conditionals: true,