Commit 31529f912b

Andrew Kelley <andrew@ziglang.org>
2023-11-04 06:08:01
zig reduce: add transformation of replacing var init with undefined
1 parent a2f4adb
Changed files (3)
lib
std
src
lib/std/zig/render.zig
@@ -24,23 +24,28 @@ pub const Fixups = struct {
     gut_functions: std.AutoHashMapUnmanaged(Ast.Node.Index, void) = .{},
     /// These global declarations will be omitted.
     omit_nodes: std.AutoHashMapUnmanaged(Ast.Node.Index, void) = .{},
+    /// These expressions will be replaced with `undefined`.
+    replace_nodes: std.AutoHashMapUnmanaged(Ast.Node.Index, void) = .{},
 
     pub fn count(f: Fixups) usize {
         return f.unused_var_decls.count() +
             f.gut_functions.count() +
-            f.omit_nodes.count();
+            f.omit_nodes.count() +
+            f.replace_nodes.count();
     }
 
     pub fn clearRetainingCapacity(f: *Fixups) void {
         f.unused_var_decls.clearRetainingCapacity();
         f.gut_functions.clearRetainingCapacity();
         f.omit_nodes.clearRetainingCapacity();
+        f.replace_nodes.clearRetainingCapacity();
     }
 
     pub fn deinit(f: *Fixups, gpa: Allocator) void {
         f.unused_var_decls.deinit(gpa);
         f.gut_functions.deinit(gpa);
         f.omit_nodes.deinit(gpa);
+        f.replace_nodes.deinit(gpa);
         f.* = undefined;
     }
 };
@@ -272,6 +277,11 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
     const main_tokens = tree.nodes.items(.main_token);
     const node_tags = tree.nodes.items(.tag);
     const datas = tree.nodes.items(.data);
+    if (r.fixups.replace_nodes.contains(node)) {
+        try ais.writer().writeAll("undefined");
+        try renderOnlySpace(r, space);
+        return;
+    }
     switch (node_tags[node]) {
         .identifier => {
             const token_index = main_tokens[node];
@@ -2775,6 +2785,19 @@ fn renderSpace(r: *Render, token_index: Ast.TokenIndex, lexeme_len: usize, space
     }
 }
 
+fn renderOnlySpace(r: *Render, space: Space) Error!void {
+    const ais = r.ais;
+    switch (space) {
+        .none => {},
+        .space => try ais.writer().writeByte(' '),
+        .newline => try ais.insertNewline(),
+        .comma => try ais.writer().writeAll(",\n"),
+        .comma_space => try ais.writer().writeAll(", "),
+        .semicolon => try ais.writer().writeAll(";\n"),
+        .skip => unreachable,
+    }
+}
+
 const QuoteBehavior = enum {
     preserve_when_shadowing,
     eagerly_unquote,
src/reduce/Walk.zig
@@ -14,6 +14,8 @@ pub const Transformation = union(enum) {
     gut_function: Ast.Node.Index,
     /// Omit a global declaration.
     delete_node: Ast.Node.Index,
+    /// Replace an expression with `undefined`.
+    replace_with_undef: Ast.Node.Index,
 };
 
 pub const Error = error{OutOfMemory};
@@ -279,7 +281,8 @@ fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void {
                     .local_var_decl,
                     .simple_var_decl,
                     .aligned_var_decl,
-                    => try walkVarDecl(w, ast.fullVarDecl(lhs_node).?),
+                    => try walkLocalVarDecl(w, ast.fullVarDecl(lhs_node).?),
+
                     else => try walkExpression(w, lhs_node),
                 }
             }
@@ -539,7 +542,7 @@ fn walkGlobalVarDecl(w: *Walk, decl_node: Ast.Node.Index, var_decl: Ast.full.Var
     return walkExpression(w, var_decl.ast.init_node);
 }
 
-fn walkVarDecl(w: *Walk, var_decl: Ast.full.VarDecl) Error!void {
+fn walkLocalVarDecl(w: *Walk, var_decl: Ast.full.VarDecl) Error!void {
     try walkIdentifierNew(w, var_decl.ast.mut_token + 1); // name
 
     if (var_decl.ast.type_node != 0) {
@@ -559,6 +562,9 @@ fn walkVarDecl(w: *Walk, var_decl: Ast.full.VarDecl) Error!void {
     }
 
     assert(var_decl.ast.init_node != 0);
+    if (!isUndefinedIdent(w.ast, var_decl.ast.init_node)) {
+        try w.transformations.append(.{ .replace_with_undef = var_decl.ast.init_node });
+    }
 
     return walkExpression(w, var_decl.ast.init_node);
 }
@@ -588,7 +594,7 @@ fn walkBlock(
             .local_var_decl,
             .simple_var_decl,
             .aligned_var_decl,
-            => try walkVarDecl(w, ast.fullVarDecl(stmt).?),
+            => try walkLocalVarDecl(w, ast.fullVarDecl(stmt).?),
 
             else => try walkExpression(w, stmt),
         }
@@ -872,3 +878,16 @@ fn isDiscardIdent(ast: *const Ast, node: Ast.Node.Index) bool {
         else => return false,
     }
 }
+
+fn isUndefinedIdent(ast: *const Ast, node: Ast.Node.Index) bool {
+    const node_tags = ast.nodes.items(.tag);
+    const main_tokens = ast.nodes.items(.main_token);
+    switch (node_tags[node]) {
+        .identifier => {
+            const token_index = main_tokens[node];
+            const name_bytes = ast.tokenSlice(token_index);
+            return std.mem.eql(u8, name_bytes, "undefined");
+        },
+        else => return false,
+    }
+}
src/reduce.zig
@@ -253,6 +253,9 @@ fn transformationsToFixups(
         .delete_node => |decl_node| {
             try fixups.omit_nodes.put(gpa, decl_node, {});
         },
+        .replace_with_undef => |node| {
+            try fixups.replace_nodes.put(gpa, node, {});
+        },
     };
 }