aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdam Goertz <adambgoertz@gmail.com>2023-11-07 01:24:19 +0000
committerAdam Goertz <adambgoertz@gmail.com>2023-11-07 01:24:19 +0000
commitdb785e25b9808168d6259de53ffb4151a422e307 (patch)
treedef25fe78d9c7e726a22614fd7d7264842233473
parent91570cc42d4fe973d15ac05cdecff42051f154ad (diff)
downloadzig-db785e25b9808168d6259de53ffb4151a422e307.tar.gz
zig-db785e25b9808168d6259de53ffb4151a422e307.zip
Apply same reductions to while
-rw-r--r--src/reduce/Walk.zig34
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) {