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 {
2424 gut_functions: std.AutoHashMapUnmanaged(Ast.Node.Index, void) = .{},
2525 /// These global declarations will be omitted.
2626 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
2830 pub fn count(f: Fixups) usize {
2931 return f.unused_var_decls.count() +
3032 f.gut_functions.count() +
31 f.omit_nodes.count();
33 f.omit_nodes.count() +
34 f.replace_nodes.count();
3235 }
3336
3437 pub fn clearRetainingCapacity(f: *Fixups) void {
3538 f.unused_var_decls.clearRetainingCapacity();
3639 f.gut_functions.clearRetainingCapacity();
3740 f.omit_nodes.clearRetainingCapacity();
41 f.replace_nodes.clearRetainingCapacity();
3842 }
3943
4044 pub fn deinit(f: *Fixups, gpa: Allocator) void {
4145 f.unused_var_decls.deinit(gpa);
4246 f.gut_functions.deinit(gpa);
4347 f.omit_nodes.deinit(gpa);
48 f.replace_nodes.deinit(gpa);
4449 f.* = undefined;
4550 }
4651};
......@@ -272,6 +277,11 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
272277 const main_tokens = tree.nodes.items(.main_token);
273278 const node_tags = tree.nodes.items(.tag);
274279 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 }
275285 switch (node_tags[node]) {
276286 .identifier => {
277287 const token_index = main_tokens[node];
......@@ -2775,6 +2785,19 @@ fn renderSpace(r: *Render, token_index: Ast.TokenIndex, lexeme_len: usize, space
27752785 }
27762786}
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
27782801const QuoteBehavior = enum {
27792802 preserve_when_shadowing,
27802803 eagerly_unquote,
src/reduce.zig+3
......@@ -253,6 +253,9 @@ fn transformationsToFixups(
253253 .delete_node => |decl_node| {
254254 try fixups.omit_nodes.put(gpa, decl_node, {});
255255 },
256 .replace_with_undef => |node| {
257 try fixups.replace_nodes.put(gpa, node, {});
258 },
256259 };
257260}
258261
src/reduce/Walk.zig+22-3
......@@ -14,6 +14,8 @@ pub const Transformation = union(enum) {
1414 gut_function: Ast.Node.Index,
1515 /// Omit a global declaration.
1616 delete_node: Ast.Node.Index,
17 /// Replace an expression with `undefined`.
18 replace_with_undef: Ast.Node.Index,
1719};
1820
1921pub const Error = error{OutOfMemory};
......@@ -279,7 +281,8 @@ fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void {
279281 .local_var_decl,
280282 .simple_var_decl,
281283 .aligned_var_decl,
282 => try walkVarDecl(w, ast.fullVarDecl(lhs_node).?),
284 => try walkLocalVarDecl(w, ast.fullVarDecl(lhs_node).?),
285
283286 else => try walkExpression(w, lhs_node),
284287 }
285288 }
......@@ -539,7 +542,7 @@ fn walkGlobalVarDecl(w: *Walk, decl_node: Ast.Node.Index, var_decl: Ast.full.Var
539542 return walkExpression(w, var_decl.ast.init_node);
540543}
541544
542fn walkVarDecl(w: *Walk, var_decl: Ast.full.VarDecl) Error!void {
545fn walkLocalVarDecl(w: *Walk, var_decl: Ast.full.VarDecl) Error!void {
543546 try walkIdentifierNew(w, var_decl.ast.mut_token + 1); // name
544547
545548 if (var_decl.ast.type_node != 0) {
......@@ -559,6 +562,9 @@ fn walkVarDecl(w: *Walk, var_decl: Ast.full.VarDecl) Error!void {
559562 }
560563
561564 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
563569 return walkExpression(w, var_decl.ast.init_node);
564570}
......@@ -588,7 +594,7 @@ fn walkBlock(
588594 .local_var_decl,
589595 .simple_var_decl,
590596 .aligned_var_decl,
591 => try walkVarDecl(w, ast.fullVarDecl(stmt).?),
597 => try walkLocalVarDecl(w, ast.fullVarDecl(stmt).?),
592598
593599 else => try walkExpression(w, stmt),
594600 }
......@@ -872,3 +878,16 @@ fn isDiscardIdent(ast: *const Ast, node: Ast.Node.Index) bool {
872878 else => return false,
873879 }
874880}
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}