diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/reduce/Walk.zig | 34 |
1 files changed, 32 insertions, 2 deletions
diff --git a/src/reduce/Walk.zig b/src/reduce/Walk.zig index 1c1a21f993..a27d893c5d 100644 --- a/src/reduce/Walk.zig +++ b/src/reduce/Walk.zig @@ -559,7 +559,7 @@ fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void { .while_simple, .while_cont, .@"while", - => return walkWhile(w, ast.fullWhile(node).?), + => return walkWhile(w, node, ast.fullWhile(node).?), .for_simple, .@"for", @@ -863,7 +863,37 @@ fn walkSwitchCase(w: *Walk, switch_case: Ast.full.SwitchCase) Error!void { try walkExpression(w, switch_case.ast.target_expr); } -fn walkWhile(w: *Walk, while_node: Ast.full.While) Error!void { +fn walkWhile(w: *Walk, node_index: Ast.Node.Index, while_node: Ast.full.While) Error!void { + assert(while_node.ast.cond_expr != 0); + assert(while_node.ast.then_expr != 0); + + // Perform these transformations in this priority order: + // 1. If the `else` expression is missing or an empty block, replace the condition with `if (true)` if it is not already. + // 2. If the `then` block is empty, replace the condition with `if (false)` if it is not already. + // 3. If the condition is `if (true)`, replace the `if` expression with the contents of the `then` expression. + // 4. If the condition is `if (false)`, replace the `if` expression with the contents of the `else` expression. + if (!isTrueIdent(w.ast, while_node.ast.cond_expr) and + (while_node.ast.else_expr == 0 or isEmptyBlock(w.ast, while_node.ast.else_expr))) + { + try w.transformations.ensureUnusedCapacity(1); + w.transformations.appendAssumeCapacity(.{ .replace_with_true = while_node.ast.cond_expr }); + } else if (!isFalseIdent(w.ast, while_node.ast.cond_expr) and isEmptyBlock(w.ast, while_node.ast.then_expr)) { + try w.transformations.ensureUnusedCapacity(1); + w.transformations.appendAssumeCapacity(.{ .replace_with_false = while_node.ast.cond_expr }); + } else if (isTrueIdent(w.ast, while_node.ast.cond_expr)) { + try w.transformations.ensureUnusedCapacity(1); + w.transformations.appendAssumeCapacity(.{ .replace_node = .{ + .to_replace = node_index, + .replacement = while_node.ast.then_expr, + } }); + } else if (isFalseIdent(w.ast, while_node.ast.cond_expr)) { + try w.transformations.ensureUnusedCapacity(1); + w.transformations.appendAssumeCapacity(.{ .replace_node = .{ + .to_replace = node_index, + .replacement = while_node.ast.else_expr, + } }); + } + try walkExpression(w, while_node.ast.cond_expr); // condition if (while_node.ast.cont_expr != 0) { |
