eliminate_spurious_blocks(stat.body);
[].splice.apply(statements, [i, 1].concat(stat.body));
i += stat.body.length;
- } else if (stat instanceof AST_EmptyStatement) {
- CHANGED = true;
- statements.splice(i, 1);
- } else if (stat instanceof AST_Directive) {
- if (!member(stat.value, seen_dirs)) {
- i++;
- seen_dirs.push(stat.value);
- } else {
+ continue;
+ }
+ if (stat instanceof AST_Directive) {
+ if (member(stat.value, seen_dirs)) {
CHANGED = true;
statements.splice(i, 1);
+ continue;
}
- } else i++;
+ seen_dirs.push(stat.value);
+ }
+ if (stat instanceof AST_EmptyStatement) {
+ CHANGED = true;
+ statements.splice(i, 1);
+ continue;
+ }
+ i++;
}
}
return !value || value instanceof AST_UnaryPrefix && value.operator == "void";
}
+ function is_last_statement(body, stat) {
+ var index = body.lastIndexOf(stat);
+ if (index < 0) return false;
+ while (++index < body.length) {
+ if (!is_declaration(body[index])) return false;
+ }
+ return true;
+ }
+
+ function match_target(target) {
+ var block = self, stat, level = 0;
+ do {
+ do {
+ if (block === target) return true;
+ block = compressor.parent(level++);
+ } while (block instanceof AST_If && (stat = block));
+ } while (block instanceof AST_BlockStatement && is_last_statement(block.body, stat));
+ }
+
function can_merge_flow(ab) {
- if (!ab) return false;
- var lct = ab instanceof AST_LoopControl ? compressor.loopcontrol_target(ab) : null;
- return ab instanceof AST_Return && in_lambda && is_return_void(ab.value)
- || ab instanceof AST_Continue && self === loop_body(lct)
- || ab instanceof AST_Break && lct instanceof AST_BlockStatement && self === lct;
+ if (ab instanceof AST_Return) return in_lambda && is_return_void(ab.value);
+ if (!(ab instanceof AST_LoopControl)) return false;
+ var lct = compressor.loopcontrol_target(ab);
+ if (ab instanceof AST_Continue) return match_target(loop_body(lct));
+ if (lct instanceof AST_IterationStatement) return false;
+ return match_target(lct);
}
function extract_functions() {
function next_index(i) {
for (var j = i + 1; j < statements.length; j++) {
- var stat = statements[j];
- if (!(stat instanceof AST_Var && declarations_only(stat))) {
- break;
- }
+ if (!is_declaration(statements[j])) break;
}
return j;
}
function prev_index(i) {
for (var j = i; --j >= 0;) {
- var stat = statements[j];
- if (!(stat instanceof AST_Var && declarations_only(stat))) {
- break;
- }
+ if (!is_declaration(statements[j])) break;
}
return j;
}
});
}
+ function is_declaration(stat) {
+ return stat instanceof AST_Defun || stat instanceof AST_Var && declarations_only(stat);
+ }
+
function sequencesize(statements, compressor) {
if (statements.length < 2) return;
var seq = [], n = 0;
var body = stat.body;
if (seq.length > 0) body = body.drop_side_effect_free(compressor);
if (body) merge_sequence(seq, body);
- } else if (stat instanceof AST_Definitions && declarations_only(stat)
- || stat instanceof AST_Defun) {
+ } else if (is_declaration(stat)) {
statements[n++] = stat;
} else {
push_seq();
}
expect_stdout: "PASS"
}
+
+nested_if_break: {
+ options = {
+ if_return: true,
+ }
+ input: {
+ for (var i = 0; i < 3; i++)
+ L1: if ("number" == typeof i) {
+ if (0 === i) break L1;
+ console.log(i);
+ }
+ }
+ expect: {
+ for (var i = 0; i < 3; i++)
+ L1: if ("number" == typeof i)
+ if (0 !== i) console.log(i);
+ }
+ expect_stdout: [
+ "1",
+ "2",
+ ]
+}
+
+nested_if_continue: {
+ options = {
+ conditionals: true,
+ if_return: true,
+ join_vars: true,
+ loops: true,
+ }
+ input: {
+ function f(n) {
+ var i = 0;
+ do {
+ if ("number" == typeof n) {
+ if (0 === n) {
+ console.log("even", i);
+ continue;
+ }
+ if (1 === n) {
+ console.log("odd", i);
+ continue;
+ }
+ i++;
+ }
+ } while (0 <= (n -= 2));
+ }
+ f(37);
+ f(42);
+ }
+ expect: {
+ function f(n) {
+ for (var i = 0;
+ "number" == typeof n
+ && (0 !== n
+ ? 1 !== n
+ ? i++
+ : console.log("odd", i)
+ : console.log("even", i)),
+ 0 <= (n -= 2););
+ }
+ f(37);
+ f(42);
+ }
+ expect_stdout: [
+ "odd 18",
+ "even 21",
+ ]
+}