diff --git a/lib/std/zig/render.zig b/lib/std/zig/render.zig index 0578b39ff1..45aaf1bd28 100644 --- a/lib/std/zig/render.zig +++ b/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, diff --git a/src/reduce.zig b/src/reduce.zig index b882d3a283..878f99a0fa 100644 --- a/src/reduce.zig +++ b/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, {}); + }, }; } diff --git a/src/reduce/Walk.zig b/src/reduce/Walk.zig index a537e86762..5ef341fcbf 100644 --- a/src/reduce/Walk.zig +++ b/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, + } +}