return self;
});
+ function if_break_in_loop(self, compressor) {
+ function drop_it(rest) {
+ rest = as_statement_array(rest);
+ if (self.body instanceof AST_BlockStatement) {
+ self.body = self.body.clone();
+ self.body.body = rest.concat(self.body.body.slice(1));
+ self.body = self.body.transform(compressor);
+ } else {
+ self.body = make_node(AST_BlockStatement, self.body, {
+ body: rest
+ }).transform(compressor);
+ }
+ if_break_in_loop(self, compressor);
+ }
+ var first = self.body instanceof AST_BlockStatement ? self.body.body[0] : self.body;
+ if (first instanceof AST_If) {
+ if (first.body instanceof AST_Break
+ && compressor.loopcontrol_target(first.body.label) === self) {
+ if (self.condition) {
+ self.condition = make_node(AST_Binary, self.condition, {
+ left: self.condition,
+ operator: "&&",
+ right: first.condition.negate(compressor),
+ });
+ } else {
+ self.condition = first.condition.negate(compressor);
+ }
+ drop_it(first.alternative);
+ }
+ else if (first.alternative instanceof AST_Break
+ && compressor.loopcontrol_target(first.alternative.label) === self) {
+ if (self.condition) {
+ self.condition = make_node(AST_Binary, self.condition, {
+ left: self.condition,
+ operator: "&&",
+ right: first.condition,
+ });
+ } else {
+ self.condition = first.condition;
+ }
+ drop_it(first.body);
+ }
+ }
+ };
+
OPT(AST_While, function(self, compressor) {
if (!compressor.option("loops")) return self;
self = AST_DWLoop.prototype.optimize.call(self, compressor);
if (self instanceof AST_While) {
- self = make_node(AST_For, self, self);
+ if_break_in_loop(self, compressor);
+ self = make_node(AST_For, self, self).transform(compressor);
}
return self;
});
}
}
}
+ if_break_in_loop(self, compressor);
return self;
});
--- /dev/null
+while_becomes_for: {
+ options = { loops: true };
+ input: {
+ while (foo()) bar();
+ }
+ expect: {
+ for (; foo(); ) bar();
+ }
+}
+
+drop_if_break_1: {
+ options = { loops: true };
+ input: {
+ for (;;)
+ if (foo()) break;
+ }
+ expect: {
+ for (; !foo(););
+ }
+}
+
+drop_if_break_2: {
+ options = { loops: true };
+ input: {
+ for (;bar();)
+ if (foo()) break;
+ }
+ expect: {
+ for (; bar() && !foo(););
+ }
+}
+
+drop_if_break_3: {
+ options = { loops: true };
+ input: {
+ for (;bar();) {
+ if (foo()) break;
+ stuff1();
+ stuff2();
+ }
+ }
+ expect: {
+ for (; bar() && !foo();) {
+ stuff1();
+ stuff2();
+ }
+ }
+}
+
+drop_if_break_4: {
+ options = { loops: true, sequences: true };
+ input: {
+ for (;bar();) {
+ x();
+ y();
+ if (foo()) break;
+ z();
+ k();
+ }
+ }
+ expect: {
+ for (; bar() && (x(), y(), !foo());) z(), k();
+ }
+}
+
+drop_if_else_break_1: {
+ options = { loops: true };
+ input: {
+ for (;;) if (foo()) bar(); else break;
+ }
+ expect: {
+ for (; foo(); ) bar();
+ }
+}
+
+drop_if_else_break_2: {
+ options = { loops: true };
+ input: {
+ for (;bar();) {
+ if (foo()) baz();
+ else break;
+ }
+ }
+ expect: {
+ for (; bar() && foo();) baz();
+ }
+}
+
+drop_if_else_break_3: {
+ options = { loops: true };
+ input: {
+ for (;bar();) {
+ if (foo()) baz();
+ else break;
+ stuff1();
+ stuff2();
+ }
+ }
+ expect: {
+ for (; bar() && foo();) {
+ baz();
+ stuff1();
+ stuff2();
+ }
+ }
+}
+
+drop_if_else_break_4: {
+ options = { loops: true, sequences: true };
+ input: {
+ for (;bar();) {
+ x();
+ y();
+ if (foo()) baz();
+ else break;
+ z();
+ k();
+ }
+ }
+ expect: {
+ for (; bar() && (x(), y(), foo());) baz(), z(), k();
+ }
+}