authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-11-03 22:08:01-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-11-03 22:08:01-07:00
log31529f912bae6fae32d2a25e873dcc23ba4e96c4
tree7f368f3c5ecc72810595956f1066e7a555630b44
parenta2f4adbd19ffea051a4fa0318bb0154e07660e55

zig reduce: add transformation of replacing var init with undefined


3 files changed, 49 insertions(+), 4 deletions(-)

lib/std/zig/render.zig+24-1
...@@ -24,23 +24,28 @@ pub const Fixups = struct {...@@ -24,23 +24,28 @@ pub const Fixups = struct {
24 gut_functions: std.AutoHashMapUnmanaged(Ast.Node.Index, void) = .{},24 gut_functions: std.AutoHashMapUnmanaged(Ast.Node.Index, void) = .{},
25 /// These global declarations will be omitted.25 /// These global declarations will be omitted.
26 omit_nodes: std.AutoHashMapUnmanaged(Ast.Node.Index, void) = .{},26 omit_nodes: std.AutoHashMapUnmanaged(Ast.Node.Index, void) = .{},
27 /// These expressions will be replaced with `undefined`.
28 replace_nodes: std.AutoHashMapUnmanaged(Ast.Node.Index, void) = .{},
2729
28 pub fn count(f: Fixups) usize {30 pub fn count(f: Fixups) usize {
29 return f.unused_var_decls.count() +31 return f.unused_var_decls.count() +
30 f.gut_functions.count() +32 f.gut_functions.count() +
31 f.omit_nodes.count();33 f.omit_nodes.count() +
34 f.replace_nodes.count();
32 }35 }
3336
34 pub fn clearRetainingCapacity(f: *Fixups) void {37 pub fn clearRetainingCapacity(f: *Fixups) void {
35 f.unused_var_decls.clearRetainingCapacity();38 f.unused_var_decls.clearRetainingCapacity();
36 f.gut_functions.clearRetainingCapacity();39 f.gut_functions.clearRetainingCapacity();
37 f.omit_nodes.clearRetainingCapacity();40 f.omit_nodes.clearRetainingCapacity();
41 f.replace_nodes.clearRetainingCapacity();
38 }42 }
3943
40 pub fn deinit(f: *Fixups, gpa: Allocator) void {44 pub fn deinit(f: *Fixups, gpa: Allocator) void {
41 f.unused_var_decls.deinit(gpa);45 f.unused_var_decls.deinit(gpa);
42 f.gut_functions.deinit(gpa);46 f.gut_functions.deinit(gpa);
43 f.omit_nodes.deinit(gpa);47 f.omit_nodes.deinit(gpa);
48 f.replace_nodes.deinit(gpa);
44 f.* = undefined;49 f.* = undefined;
45 }50 }
46};51};
...@@ -272,6 +277,11 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {...@@ -272,6 +277,11 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
272 const main_tokens = tree.nodes.items(.main_token);277 const main_tokens = tree.nodes.items(.main_token);
273 const node_tags = tree.nodes.items(.tag);278 const node_tags = tree.nodes.items(.tag);
274 const datas = tree.nodes.items(.data);279 const datas = tree.nodes.items(.data);
280 if (r.fixups.replace_nodes.contains(node)) {
281 try ais.writer().writeAll("undefined");
282 try renderOnlySpace(r, space);
283 return;
284 }
275 switch (node_tags[node]) {285 switch (node_tags[node]) {
276 .identifier => {286 .identifier => {
277 const token_index = main_tokens[node];287 const token_index = main_tokens[node];
...@@ -2775,6 +2785,19 @@ fn renderSpace(r: *Render, token_index: Ast.TokenIndex, lexeme_len: usize, space...@@ -2775,6 +2785,19 @@ fn renderSpace(r: *Render, token_index: Ast.TokenIndex, lexeme_len: usize, space
2775 }2785 }
2776}2786}
27772787
2788fn renderOnlySpace(r: *Render, space: Space) Error!void {
2789 const ais = r.ais;
2790 switch (space) {
2791 .none => {},
2792 .space => try ais.writer().writeByte(' '),
2793 .newline => try ais.insertNewline(),
2794 .comma => try ais.writer().writeAll(",\n"),
2795 .comma_space => try ais.writer().writeAll(", "),
2796 .semicolon => try ais.writer().writeAll(";\n"),
2797 .skip => unreachable,
2798 }
2799}
2800
2778const QuoteBehavior = enum {2801const QuoteBehavior = enum {
2779 preserve_when_shadowing,2802 preserve_when_shadowing,
2780 eagerly_unquote,2803 eagerly_unquote,
src/reduce.zig+3
...@@ -253,6 +253,9 @@ fn transformationsToFixups(...@@ -253,6 +253,9 @@ fn transformationsToFixups(
253 .delete_node => |decl_node| {253 .delete_node => |decl_node| {
254 try fixups.omit_nodes.put(gpa, decl_node, {});254 try fixups.omit_nodes.put(gpa, decl_node, {});
255 },255 },
256 .replace_with_undef => |node| {
257 try fixups.replace_nodes.put(gpa, node, {});
258 },
256 };259 };
257}260}
258261
src/reduce/Walk.zig+22-3
...@@ -14,6 +14,8 @@ pub const Transformation = union(enum) {...@@ -14,6 +14,8 @@ pub const Transformation = union(enum) {
14 gut_function: Ast.Node.Index,14 gut_function: Ast.Node.Index,
15 /// Omit a global declaration.15 /// Omit a global declaration.
16 delete_node: Ast.Node.Index,16 delete_node: Ast.Node.Index,
17 /// Replace an expression with `undefined`.
18 replace_with_undef: Ast.Node.Index,
17};19};
1820
19pub const Error = error{OutOfMemory};21pub const Error = error{OutOfMemory};
...@@ -279,7 +281,8 @@ fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void {...@@ -279,7 +281,8 @@ fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void {
279 .local_var_decl,281 .local_var_decl,
280 .simple_var_decl,282 .simple_var_decl,
281 .aligned_var_decl,283 .aligned_var_decl,
282 => try walkVarDecl(w, ast.fullVarDecl(lhs_node).?),284 => try walkLocalVarDecl(w, ast.fullVarDecl(lhs_node).?),
285
283 else => try walkExpression(w, lhs_node),286 else => try walkExpression(w, lhs_node),
284 }287 }
285 }288 }
...@@ -539,7 +542,7 @@ fn walkGlobalVarDecl(w: *Walk, decl_node: Ast.Node.Index, var_decl: Ast.full.Var...@@ -539,7 +542,7 @@ fn walkGlobalVarDecl(w: *Walk, decl_node: Ast.Node.Index, var_decl: Ast.full.Var
539 return walkExpression(w, var_decl.ast.init_node);542 return walkExpression(w, var_decl.ast.init_node);
540}543}
541544
542fn walkVarDecl(w: *Walk, var_decl: Ast.full.VarDecl) Error!void {545fn walkLocalVarDecl(w: *Walk, var_decl: Ast.full.VarDecl) Error!void {
543 try walkIdentifierNew(w, var_decl.ast.mut_token + 1); // name546 try walkIdentifierNew(w, var_decl.ast.mut_token + 1); // name
544547
545 if (var_decl.ast.type_node != 0) {548 if (var_decl.ast.type_node != 0) {
...@@ -559,6 +562,9 @@ fn walkVarDecl(w: *Walk, var_decl: Ast.full.VarDecl) Error!void {...@@ -559,6 +562,9 @@ fn walkVarDecl(w: *Walk, var_decl: Ast.full.VarDecl) Error!void {
559 }562 }
560563
561 assert(var_decl.ast.init_node != 0);564 assert(var_decl.ast.init_node != 0);
565 if (!isUndefinedIdent(w.ast, var_decl.ast.init_node)) {
566 try w.transformations.append(.{ .replace_with_undef = var_decl.ast.init_node });
567 }
562568
563 return walkExpression(w, var_decl.ast.init_node);569 return walkExpression(w, var_decl.ast.init_node);
564}570}
...@@ -588,7 +594,7 @@ fn walkBlock(...@@ -588,7 +594,7 @@ fn walkBlock(
588 .local_var_decl,594 .local_var_decl,
589 .simple_var_decl,595 .simple_var_decl,
590 .aligned_var_decl,596 .aligned_var_decl,
591 => try walkVarDecl(w, ast.fullVarDecl(stmt).?),597 => try walkLocalVarDecl(w, ast.fullVarDecl(stmt).?),
592598
593 else => try walkExpression(w, stmt),599 else => try walkExpression(w, stmt),
594 }600 }
...@@ -872,3 +878,16 @@ fn isDiscardIdent(ast: *const Ast, node: Ast.Node.Index) bool {...@@ -872,3 +878,16 @@ fn isDiscardIdent(ast: *const Ast, node: Ast.Node.Index) bool {
872 else => return false,878 else => return false,
873 }879 }
874}880}
881
882fn isUndefinedIdent(ast: *const Ast, node: Ast.Node.Index) bool {
883 const node_tags = ast.nodes.items(.tag);
884 const main_tokens = ast.nodes.items(.main_token);
885 switch (node_tags[node]) {
886 .identifier => {
887 const token_index = main_tokens[node];
888 const name_bytes = ast.tokenSlice(token_index);
889 return std.mem.eql(u8, name_bytes, "undefined");
890 },
891 else => return false,
892 }
893}