authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-11-02 15:22:09-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-11-03 20:05:32-07:00
log5f1f14519949ea8c9fc136e14b01b419fe59b751
tree6c150486533ccdca20409c0b367d4cf6528acce9
parent3263d6e6aba197656ba6b0e35330ce4d756eaf60

add a transformation for gutting the body of a function


2 files changed, 123 insertions(+), 46 deletions(-)

lib/std/zig/render.zig+106-45
...@@ -18,6 +18,11 @@ pub const Fixups = struct {...@@ -18,6 +18,11 @@ pub const Fixups = struct {
18 /// The key is the mut token (`var`/`const`) of the variable declaration18 /// The key is the mut token (`var`/`const`) of the variable declaration
19 /// that should have a `_ = foo;` inserted afterwards.19 /// that should have a `_ = foo;` inserted afterwards.
20 unused_var_decls: std.AutoHashMapUnmanaged(Ast.TokenIndex, void) = .{},20 unused_var_decls: std.AutoHashMapUnmanaged(Ast.TokenIndex, void) = .{},
21 /// The functions in this unordered set of indices will render with a
22 /// function body of `@trap()` instead, with all parameters discarded.
23 /// The indexes correspond to the order in which the functions appear in
24 /// the file.
25 gut_functions: std.AutoHashMapUnmanaged(u32, void) = .{},
2126
22 pub fn count(f: Fixups) usize {27 pub fn count(f: Fixups) usize {
23 return f.unused_var_decls.count();28 return f.unused_var_decls.count();
...@@ -34,6 +39,9 @@ const Render = struct {...@@ -34,6 +39,9 @@ const Render = struct {
34 ais: *Ais,39 ais: *Ais,
35 tree: Ast,40 tree: Ast,
36 fixups: Fixups,41 fixups: Fixups,
42 /// Keeps track of how many function declarations we have seen so far. Used
43 /// by Fixups.
44 function_index: u32,
37};45};
3846
39pub fn renderTree(buffer: *std.ArrayList(u8), tree: Ast, fixups: Fixups) Error!void {47pub fn renderTree(buffer: *std.ArrayList(u8), tree: Ast, fixups: Fixups) Error!void {
...@@ -47,24 +55,25 @@ pub fn renderTree(buffer: *std.ArrayList(u8), tree: Ast, fixups: Fixups) Error!v...@@ -47,24 +55,25 @@ pub fn renderTree(buffer: *std.ArrayList(u8), tree: Ast, fixups: Fixups) Error!v
47 .ais = &auto_indenting_stream,55 .ais = &auto_indenting_stream,
48 .tree = tree,56 .tree = tree,
49 .fixups = fixups,57 .fixups = fixups,
58 .function_index = 0,
50 };59 };
5160
52 // Render all the line comments at the beginning of the file.61 // Render all the line comments at the beginning of the file.
53 const comment_end_loc = tree.tokens.items(.start)[0];62 const comment_end_loc = tree.tokens.items(.start)[0];
54 _ = try renderComments(r, 0, comment_end_loc);63 _ = try renderComments(&r, 0, comment_end_loc);
5564
56 if (tree.tokens.items(.tag)[0] == .container_doc_comment) {65 if (tree.tokens.items(.tag)[0] == .container_doc_comment) {
57 try renderContainerDocComments(r, 0);66 try renderContainerDocComments(&r, 0);
58 }67 }
5968
60 if (tree.mode == .zon) {69 if (tree.mode == .zon) {
61 try renderExpression(70 try renderExpression(
62 r,71 &r,
63 tree.nodes.items(.data)[0].lhs,72 tree.nodes.items(.data)[0].lhs,
64 .newline,73 .newline,
65 );74 );
66 } else {75 } else {
67 try renderMembers(r, tree.rootDecls());76 try renderMembers(&r, tree.rootDecls());
68 }77 }
6978
70 if (auto_indenting_stream.disabled_offset) |disabled_offset| {79 if (auto_indenting_stream.disabled_offset) |disabled_offset| {
...@@ -73,7 +82,7 @@ pub fn renderTree(buffer: *std.ArrayList(u8), tree: Ast, fixups: Fixups) Error!v...@@ -73,7 +82,7 @@ pub fn renderTree(buffer: *std.ArrayList(u8), tree: Ast, fixups: Fixups) Error!v
73}82}
7483
75/// Render all members in the given slice, keeping empty lines where appropriate84/// Render all members in the given slice, keeping empty lines where appropriate
76fn renderMembers(r: Render, members: []const Ast.Node.Index) Error!void {85fn renderMembers(r: *Render, members: []const Ast.Node.Index) Error!void {
77 const tree = r.tree;86 const tree = r.tree;
78 if (members.len == 0) return;87 if (members.len == 0) return;
79 const container: Container = for (members) |member| {88 const container: Container = for (members) |member| {
...@@ -93,7 +102,7 @@ const Container = enum {...@@ -93,7 +102,7 @@ const Container = enum {
93};102};
94103
95fn renderMember(104fn renderMember(
96 r: Render,105 r: *Render,
97 container: Container,106 container: Container,
98 decl: Ast.Node.Index,107 decl: Ast.Node.Index,
99 space: Space,108 space: Space,
...@@ -106,6 +115,8 @@ fn renderMember(...@@ -106,6 +115,8 @@ fn renderMember(
106 try renderDocComments(r, tree.firstToken(decl));115 try renderDocComments(r, tree.firstToken(decl));
107 switch (tree.nodes.items(.tag)[decl]) {116 switch (tree.nodes.items(.tag)[decl]) {
108 .fn_decl => {117 .fn_decl => {
118 const this_index = r.function_index;
119 r.function_index += 1;
109 // Some examples:120 // Some examples:
110 // pub extern "foo" fn ...121 // pub extern "foo" fn ...
111 // export fn ...122 // export fn ...
...@@ -150,7 +161,19 @@ fn renderMember(...@@ -150,7 +161,19 @@ fn renderMember(
150 }161 }
151 assert(datas[decl].rhs != 0);162 assert(datas[decl].rhs != 0);
152 try renderExpression(r, fn_proto, .space);163 try renderExpression(r, fn_proto, .space);
153 return renderExpression(r, datas[decl].rhs, space);164 const body_node = datas[decl].rhs;
165 if (r.fixups.gut_functions.contains(this_index)) {
166 ais.pushIndent();
167 const lbrace = tree.nodes.items(.main_token)[body_node];
168 try renderToken(r, lbrace, .newline);
169 try discardAllParams(r, fn_proto);
170 try ais.writer().writeAll("@trap();");
171 ais.popIndent();
172 try ais.insertNewline();
173 try renderToken(r, tree.lastToken(body_node), space); // rbrace
174 } else {
175 return renderExpression(r, body_node, space);
176 }
154 },177 },
155 .fn_proto_simple,178 .fn_proto_simple,
156 .fn_proto_multi,179 .fn_proto_multi,
...@@ -227,7 +250,7 @@ fn renderMember(...@@ -227,7 +250,7 @@ fn renderMember(
227}250}
228251
229/// Render all expressions in the slice, keeping empty lines where appropriate252/// Render all expressions in the slice, keeping empty lines where appropriate
230fn renderExpressions(r: Render, expressions: []const Ast.Node.Index, space: Space) Error!void {253fn renderExpressions(r: *Render, expressions: []const Ast.Node.Index, space: Space) Error!void {
231 if (expressions.len == 0) return;254 if (expressions.len == 0) return;
232 try renderExpression(r, expressions[0], space);255 try renderExpression(r, expressions[0], space);
233 for (expressions[1..]) |expression| {256 for (expressions[1..]) |expression| {
...@@ -236,7 +259,7 @@ fn renderExpressions(r: Render, expressions: []const Ast.Node.Index, space: Spac...@@ -236,7 +259,7 @@ fn renderExpressions(r: Render, expressions: []const Ast.Node.Index, space: Spac
236 }259 }
237}260}
238261
239fn renderExpression(r: Render, node: Ast.Node.Index, space: Space) Error!void {262fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
240 const tree = r.tree;263 const tree = r.tree;
241 const ais = r.ais;264 const ais = r.ais;
242 const token_tags = tree.tokens.items(.tag);265 const token_tags = tree.tokens.items(.tag);
...@@ -815,7 +838,7 @@ fn renderExpression(r: Render, node: Ast.Node.Index, space: Space) Error!void {...@@ -815,7 +838,7 @@ fn renderExpression(r: Render, node: Ast.Node.Index, space: Space) Error!void {
815}838}
816839
817fn renderArrayType(840fn renderArrayType(
818 r: Render,841 r: *Render,
819 array_type: Ast.full.ArrayType,842 array_type: Ast.full.ArrayType,
820 space: Space,843 space: Space,
821) Error!void {844) Error!void {
...@@ -836,7 +859,7 @@ fn renderArrayType(...@@ -836,7 +859,7 @@ fn renderArrayType(
836 return renderExpression(r, array_type.ast.elem_type, space);859 return renderExpression(r, array_type.ast.elem_type, space);
837}860}
838861
839fn renderPtrType(r: Render, ptr_type: Ast.full.PtrType, space: Space) Error!void {862fn renderPtrType(r: *Render, ptr_type: Ast.full.PtrType, space: Space) Error!void {
840 const tree = r.tree;863 const tree = r.tree;
841 switch (ptr_type.size) {864 switch (ptr_type.size) {
842 .One => {865 .One => {
...@@ -925,7 +948,7 @@ fn renderPtrType(r: Render, ptr_type: Ast.full.PtrType, space: Space) Error!void...@@ -925,7 +948,7 @@ fn renderPtrType(r: Render, ptr_type: Ast.full.PtrType, space: Space) Error!void
925}948}
926949
927fn renderSlice(950fn renderSlice(
928 r: Render,951 r: *Render,
929 slice_node: Ast.Node.Index,952 slice_node: Ast.Node.Index,
930 slice: Ast.full.Slice,953 slice: Ast.full.Slice,
931 space: Space,954 space: Space,
...@@ -960,7 +983,7 @@ fn renderSlice(...@@ -960,7 +983,7 @@ fn renderSlice(
960}983}
961984
962fn renderAsmOutput(985fn renderAsmOutput(
963 r: Render,986 r: *Render,
964 asm_output: Ast.Node.Index,987 asm_output: Ast.Node.Index,
965 space: Space,988 space: Space,
966) Error!void {989) Error!void {
...@@ -989,7 +1012,7 @@ fn renderAsmOutput(...@@ -989,7 +1012,7 @@ fn renderAsmOutput(
989}1012}
9901013
991fn renderAsmInput(1014fn renderAsmInput(
992 r: Render,1015 r: *Render,
993 asm_input: Ast.Node.Index,1016 asm_input: Ast.Node.Index,
994 space: Space,1017 space: Space,
995) Error!void {1018) Error!void {
...@@ -1010,7 +1033,25 @@ fn renderAsmInput(...@@ -1010,7 +1033,25 @@ fn renderAsmInput(
1010}1033}
10111034
1012fn renderVarDecl(1035fn renderVarDecl(
1013 r: Render,1036 r: *Render,
1037 var_decl: Ast.full.VarDecl,
1038 /// Destructures intentionally ignore leading `comptime` tokens.
1039 ignore_comptime_token: bool,
1040 /// `comma_space` and `space` are used for destructure LHS decls.
1041 space: Space,
1042) Error!void {
1043 try renderVarDeclWithoutFixups(r, var_decl, ignore_comptime_token, space);
1044 if (r.fixups.unused_var_decls.contains(var_decl.ast.mut_token)) {
1045 // Discard the variable like this: `_ = foo;`
1046 const w = r.ais.writer();
1047 try w.writeAll("_ = ");
1048 try w.writeAll(tokenSliceForRender(r.tree, var_decl.ast.mut_token + 1));
1049 try w.writeAll(";\n");
1050 }
1051}
1052
1053fn renderVarDeclWithoutFixups(
1054 r: *Render,
1014 var_decl: Ast.full.VarDecl,1055 var_decl: Ast.full.VarDecl,
1015 /// Destructures intentionally ignore leading `comptime` tokens.1056 /// Destructures intentionally ignore leading `comptime` tokens.
1016 ignore_comptime_token: bool,1057 ignore_comptime_token: bool,
...@@ -1131,7 +1172,7 @@ fn renderVarDecl(...@@ -1131,7 +1172,7 @@ fn renderVarDecl(
1131 return renderExpression(r, var_decl.ast.init_node, space); // ;1172 return renderExpression(r, var_decl.ast.init_node, space); // ;
1132}1173}
11331174
1134fn renderIf(r: Render, if_node: Ast.full.If, space: Space) Error!void {1175fn renderIf(r: *Render, if_node: Ast.full.If, space: Space) Error!void {
1135 return renderWhile(r, .{1176 return renderWhile(r, .{
1136 .ast = .{1177 .ast = .{
1137 .while_token = if_node.ast.if_token,1178 .while_token = if_node.ast.if_token,
...@@ -1150,7 +1191,7 @@ fn renderIf(r: Render, if_node: Ast.full.If, space: Space) Error!void {...@@ -1150,7 +1191,7 @@ fn renderIf(r: Render, if_node: Ast.full.If, space: Space) Error!void {
11501191
1151/// Note that this function is additionally used to render if expressions, with1192/// Note that this function is additionally used to render if expressions, with
1152/// respective values set to null.1193/// respective values set to null.
1153fn renderWhile(r: Render, while_node: Ast.full.While, space: Space) Error!void {1194fn renderWhile(r: *Render, while_node: Ast.full.While, space: Space) Error!void {
1154 const tree = r.tree;1195 const tree = r.tree;
1155 const token_tags = tree.tokens.items(.tag);1196 const token_tags = tree.tokens.items(.tag);
11561197
...@@ -1214,7 +1255,7 @@ fn renderWhile(r: Render, while_node: Ast.full.While, space: Space) Error!void {...@@ -1214,7 +1255,7 @@ fn renderWhile(r: Render, while_node: Ast.full.While, space: Space) Error!void {
1214}1255}
12151256
1216fn renderThenElse(1257fn renderThenElse(
1217 r: Render,1258 r: *Render,
1218 last_prefix_token: Ast.TokenIndex,1259 last_prefix_token: Ast.TokenIndex,
1219 then_expr: Ast.Node.Index,1260 then_expr: Ast.Node.Index,
1220 else_token: Ast.TokenIndex,1261 else_token: Ast.TokenIndex,
...@@ -1275,7 +1316,7 @@ fn renderThenElse(...@@ -1275,7 +1316,7 @@ fn renderThenElse(
1275 }1316 }
1276}1317}
12771318
1278fn renderFor(r: Render, for_node: Ast.full.For, space: Space) Error!void {1319fn renderFor(r: *Render, for_node: Ast.full.For, space: Space) Error!void {
1279 const tree = r.tree;1320 const tree = r.tree;
1280 const ais = r.ais;1321 const ais = r.ais;
1281 const token_tags = tree.tokens.items(.tag);1322 const token_tags = tree.tokens.items(.tag);
...@@ -1346,7 +1387,7 @@ fn renderFor(r: Render, for_node: Ast.full.For, space: Space) Error!void {...@@ -1346,7 +1387,7 @@ fn renderFor(r: Render, for_node: Ast.full.For, space: Space) Error!void {
1346}1387}
13471388
1348fn renderContainerField(1389fn renderContainerField(
1349 r: Render,1390 r: *Render,
1350 container: Container,1391 container: Container,
1351 field_param: Ast.full.ContainerField,1392 field_param: Ast.full.ContainerField,
1352 space: Space,1393 space: Space,
...@@ -1450,7 +1491,7 @@ fn renderContainerField(...@@ -1450,7 +1491,7 @@ fn renderContainerField(
1450}1491}
14511492
1452fn renderBuiltinCall(1493fn renderBuiltinCall(
1453 r: Render,1494 r: *Render,
1454 builtin_token: Ast.TokenIndex,1495 builtin_token: Ast.TokenIndex,
1455 params: []const Ast.Node.Index,1496 params: []const Ast.Node.Index,
1456 space: Space,1497 space: Space,
...@@ -1588,7 +1629,7 @@ fn renderBuiltinCall(...@@ -1588,7 +1629,7 @@ fn renderBuiltinCall(
1588 }1629 }
1589}1630}
15901631
1591fn renderFnProto(r: Render, fn_proto: Ast.full.FnProto, space: Space) Error!void {1632fn renderFnProto(r: *Render, fn_proto: Ast.full.FnProto, space: Space) Error!void {
1592 const tree = r.tree;1633 const tree = r.tree;
1593 const ais = r.ais;1634 const ais = r.ais;
1594 const token_tags = tree.tokens.items(.tag);1635 const token_tags = tree.tokens.items(.tag);
...@@ -1806,7 +1847,7 @@ fn renderFnProto(r: Render, fn_proto: Ast.full.FnProto, space: Space) Error!void...@@ -1806,7 +1847,7 @@ fn renderFnProto(r: Render, fn_proto: Ast.full.FnProto, space: Space) Error!void
1806}1847}
18071848
1808fn renderSwitchCase(1849fn renderSwitchCase(
1809 r: Render,1850 r: *Render,
1810 switch_case: Ast.full.SwitchCase,1851 switch_case: Ast.full.SwitchCase,
1811 space: Space,1852 space: Space,
1812) Error!void {1853) Error!void {
...@@ -1869,7 +1910,7 @@ fn renderSwitchCase(...@@ -1869,7 +1910,7 @@ fn renderSwitchCase(
1869}1910}
18701911
1871fn renderBlock(1912fn renderBlock(
1872 r: Render,1913 r: *Render,
1873 block_node: Ast.Node.Index,1914 block_node: Ast.Node.Index,
1874 statements: []const Ast.Node.Index,1915 statements: []const Ast.Node.Index,
1875 space: Space,1916 space: Space,
...@@ -1910,7 +1951,7 @@ fn renderBlock(...@@ -1910,7 +1951,7 @@ fn renderBlock(
1910}1951}
19111952
1912fn renderStructInit(1953fn renderStructInit(
1913 r: Render,1954 r: *Render,
1914 struct_node: Ast.Node.Index,1955 struct_node: Ast.Node.Index,
1915 struct_init: Ast.full.StructInit,1956 struct_init: Ast.full.StructInit,
1916 space: Space,1957 space: Space,
...@@ -1975,7 +2016,7 @@ fn renderStructInit(...@@ -1975,7 +2016,7 @@ fn renderStructInit(
1975}2016}
19762017
1977fn renderArrayInit(2018fn renderArrayInit(
1978 r: Render,2019 r: *Render,
1979 array_init: Ast.full.ArrayInit,2020 array_init: Ast.full.ArrayInit,
1980 space: Space,2021 space: Space,
1981) Error!void {2022) Error!void {
...@@ -2095,6 +2136,7 @@ fn renderArrayInit(...@@ -2095,6 +2136,7 @@ fn renderArrayInit(
2095 .ais = &auto_indenting_stream,2136 .ais = &auto_indenting_stream,
2096 .tree = r.tree,2137 .tree = r.tree,
2097 .fixups = r.fixups,2138 .fixups = r.fixups,
2139 .function_index = r.function_index,
2098 };2140 };
20992141
2100 // Calculate size of columns in current section2142 // Calculate size of columns in current section
...@@ -2106,7 +2148,7 @@ fn renderArrayInit(...@@ -2106,7 +2148,7 @@ fn renderArrayInit(
2106 sub_expr_buffer_starts[i] = start;2148 sub_expr_buffer_starts[i] = start;
21072149
2108 if (i + 1 < section_exprs.len) {2150 if (i + 1 < section_exprs.len) {
2109 try renderExpression(sub_render, expr, .none);2151 try renderExpression(&sub_render, expr, .none);
2110 const width = sub_expr_buffer.items.len - start;2152 const width = sub_expr_buffer.items.len - start;
2111 const this_contains_newline = mem.indexOfScalar(u8, sub_expr_buffer.items[start..], '\n') != null;2153 const this_contains_newline = mem.indexOfScalar(u8, sub_expr_buffer.items[start..], '\n') != null;
2112 contains_newline = contains_newline or this_contains_newline;2154 contains_newline = contains_newline or this_contains_newline;
...@@ -2126,7 +2168,7 @@ fn renderArrayInit(...@@ -2126,7 +2168,7 @@ fn renderArrayInit(
2126 column_counter = 0;2168 column_counter = 0;
2127 }2169 }
2128 } else {2170 } else {
2129 try renderExpression(sub_render, expr, .comma);2171 try renderExpression(&sub_render, expr, .comma);
2130 const width = sub_expr_buffer.items.len - start - 2;2172 const width = sub_expr_buffer.items.len - start - 2;
2131 const this_contains_newline = mem.indexOfScalar(u8, sub_expr_buffer.items[start .. sub_expr_buffer.items.len - 1], '\n') != null;2173 const this_contains_newline = mem.indexOfScalar(u8, sub_expr_buffer.items[start .. sub_expr_buffer.items.len - 1], '\n') != null;
2132 contains_newline = contains_newline or this_contains_newline;2174 contains_newline = contains_newline or this_contains_newline;
...@@ -2201,7 +2243,7 @@ fn renderArrayInit(...@@ -2201,7 +2243,7 @@ fn renderArrayInit(
2201}2243}
22022244
2203fn renderContainerDecl(2245fn renderContainerDecl(
2204 r: Render,2246 r: *Render,
2205 container_decl_node: Ast.Node.Index,2247 container_decl_node: Ast.Node.Index,
2206 container_decl: Ast.full.ContainerDecl,2248 container_decl: Ast.full.ContainerDecl,
2207 space: Space,2249 space: Space,
...@@ -2317,7 +2359,7 @@ fn renderContainerDecl(...@@ -2317,7 +2359,7 @@ fn renderContainerDecl(
2317}2359}
23182360
2319fn renderAsm(2361fn renderAsm(
2320 r: Render,2362 r: *Render,
2321 asm_node: Ast.full.Asm,2363 asm_node: Ast.full.Asm,
2322 space: Space,2364 space: Space,
2323) Error!void {2365) Error!void {
...@@ -2476,7 +2518,7 @@ fn renderAsm(...@@ -2476,7 +2518,7 @@ fn renderAsm(
2476}2518}
24772519
2478fn renderCall(2520fn renderCall(
2479 r: Render,2521 r: *Render,
2480 call: Ast.full.Call,2522 call: Ast.full.Call,
2481 space: Space,2523 space: Space,
2482) Error!void {2524) Error!void {
...@@ -2488,7 +2530,7 @@ fn renderCall(...@@ -2488,7 +2530,7 @@ fn renderCall(
2488}2530}
24892531
2490fn renderParamList(2532fn renderParamList(
2491 r: Render,2533 r: *Render,
2492 lparen: Ast.TokenIndex,2534 lparen: Ast.TokenIndex,
2493 params: []const Ast.Node.Index,2535 params: []const Ast.Node.Index,
2494 space: Space,2536 space: Space,
...@@ -2557,7 +2599,7 @@ fn renderParamList(...@@ -2557,7 +2599,7 @@ fn renderParamList(
25572599
2558/// Renders the given expression indented, popping the indent before rendering2600/// Renders the given expression indented, popping the indent before rendering
2559/// any following line comments2601/// any following line comments
2560fn renderExpressionIndented(r: Render, node: Ast.Node.Index, space: Space) Error!void {2602fn renderExpressionIndented(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
2561 const tree = r.tree;2603 const tree = r.tree;
2562 const ais = r.ais;2604 const ais = r.ais;
2563 const token_starts = tree.tokens.items(.start);2605 const token_starts = tree.tokens.items(.start);
...@@ -2617,7 +2659,7 @@ fn renderExpressionIndented(r: Render, node: Ast.Node.Index, space: Space) Error...@@ -2617,7 +2659,7 @@ fn renderExpressionIndented(r: Render, node: Ast.Node.Index, space: Space) Error
26172659
2618/// Render an expression, and the comma that follows it, if it is present in the source.2660/// Render an expression, and the comma that follows it, if it is present in the source.
2619/// If a comma is present, and `space` is `Space.comma`, render only a single comma.2661/// If a comma is present, and `space` is `Space.comma`, render only a single comma.
2620fn renderExpressionComma(r: Render, node: Ast.Node.Index, space: Space) Error!void {2662fn renderExpressionComma(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
2621 const tree = r.tree;2663 const tree = r.tree;
2622 const token_tags = tree.tokens.items(.tag);2664 const token_tags = tree.tokens.items(.tag);
2623 const maybe_comma = tree.lastToken(node) + 1;2665 const maybe_comma = tree.lastToken(node) + 1;
...@@ -2631,7 +2673,7 @@ fn renderExpressionComma(r: Render, node: Ast.Node.Index, space: Space) Error!vo...@@ -2631,7 +2673,7 @@ fn renderExpressionComma(r: Render, node: Ast.Node.Index, space: Space) Error!vo
26312673
2632/// Render a token, and the comma that follows it, if it is present in the source.2674/// Render a token, and the comma that follows it, if it is present in the source.
2633/// If a comma is present, and `space` is `Space.comma`, render only a single comma.2675/// If a comma is present, and `space` is `Space.comma`, render only a single comma.
2634fn renderTokenComma(r: Render, token: Ast.TokenIndex, space: Space) Error!void {2676fn renderTokenComma(r: *Render, token: Ast.TokenIndex, space: Space) Error!void {
2635 const tree = r.tree;2677 const tree = r.tree;
2636 const token_tags = tree.tokens.items(.tag);2678 const token_tags = tree.tokens.items(.tag);
2637 const maybe_comma = token + 1;2679 const maybe_comma = token + 1;
...@@ -2645,7 +2687,7 @@ fn renderTokenComma(r: Render, token: Ast.TokenIndex, space: Space) Error!void {...@@ -2645,7 +2687,7 @@ fn renderTokenComma(r: Render, token: Ast.TokenIndex, space: Space) Error!void {
26452687
2646/// Render an identifier, and the comma that follows it, if it is present in the source.2688/// Render an identifier, and the comma that follows it, if it is present in the source.
2647/// If a comma is present, and `space` is `Space.comma`, render only a single comma.2689/// If a comma is present, and `space` is `Space.comma`, render only a single comma.
2648fn renderIdentifierComma(r: Render, token: Ast.TokenIndex, space: Space, quote: QuoteBehavior) Error!void {2690fn renderIdentifierComma(r: *Render, token: Ast.TokenIndex, space: Space, quote: QuoteBehavior) Error!void {
2649 const tree = r.tree;2691 const tree = r.tree;
2650 const token_tags = tree.tokens.items(.tag);2692 const token_tags = tree.tokens.items(.tag);
2651 const maybe_comma = token + 1;2693 const maybe_comma = token + 1;
...@@ -2678,7 +2720,7 @@ const Space = enum {...@@ -2678,7 +2720,7 @@ const Space = enum {
2678 skip,2720 skip,
2679};2721};
26802722
2681fn renderToken(r: Render, token_index: Ast.TokenIndex, space: Space) Error!void {2723fn renderToken(r: *Render, token_index: Ast.TokenIndex, space: Space) Error!void {
2682 const tree = r.tree;2724 const tree = r.tree;
2683 const ais = r.ais;2725 const ais = r.ais;
2684 const lexeme = tokenSliceForRender(tree, token_index);2726 const lexeme = tokenSliceForRender(tree, token_index);
...@@ -2686,7 +2728,7 @@ fn renderToken(r: Render, token_index: Ast.TokenIndex, space: Space) Error!void...@@ -2686,7 +2728,7 @@ fn renderToken(r: Render, token_index: Ast.TokenIndex, space: Space) Error!void
2686 try renderSpace(r, token_index, lexeme.len, space);2728 try renderSpace(r, token_index, lexeme.len, space);
2687}2729}
26882730
2689fn renderSpace(r: Render, token_index: Ast.TokenIndex, lexeme_len: usize, space: Space) Error!void {2731fn renderSpace(r: *Render, token_index: Ast.TokenIndex, lexeme_len: usize, space: Space) Error!void {
2690 const tree = r.tree;2732 const tree = r.tree;
2691 const ais = r.ais;2733 const ais = r.ais;
2692 const token_tags = tree.tokens.items(.tag);2734 const token_tags = tree.tokens.items(.tag);
...@@ -2734,7 +2776,7 @@ const QuoteBehavior = enum {...@@ -2734,7 +2776,7 @@ const QuoteBehavior = enum {
2734 eagerly_unquote_except_underscore,2776 eagerly_unquote_except_underscore,
2735};2777};
27362778
2737fn renderIdentifier(r: Render, token_index: Ast.TokenIndex, space: Space, quote: QuoteBehavior) Error!void {2779fn renderIdentifier(r: *Render, token_index: Ast.TokenIndex, space: Space, quote: QuoteBehavior) Error!void {
2738 const tree = r.tree;2780 const tree = r.tree;
2739 const token_tags = tree.tokens.items(.tag);2781 const token_tags = tree.tokens.items(.tag);
2740 assert(token_tags[token_index] == .identifier);2782 assert(token_tags[token_index] == .identifier);
...@@ -2836,7 +2878,7 @@ fn renderIdentifier(r: Render, token_index: Ast.TokenIndex, space: Space, quote:...@@ -2836,7 +2878,7 @@ fn renderIdentifier(r: Render, token_index: Ast.TokenIndex, space: Space, quote:
2836// Renders a @"" quoted identifier, normalizing escapes.2878// Renders a @"" quoted identifier, normalizing escapes.
2837// Unnecessary escapes are un-escaped, and \u escapes are normalized to \x when they fit.2879// Unnecessary escapes are un-escaped, and \u escapes are normalized to \x when they fit.
2838// If unquote is true, the @"" is removed and the result is a bare symbol whose validity is asserted.2880// If unquote is true, the @"" is removed and the result is a bare symbol whose validity is asserted.
2839fn renderQuotedIdentifier(r: Render, token_index: Ast.TokenIndex, space: Space, comptime unquote: bool) !void {2881fn renderQuotedIdentifier(r: *Render, token_index: Ast.TokenIndex, space: Space, comptime unquote: bool) !void {
2840 const tree = r.tree;2882 const tree = r.tree;
2841 const ais = r.ais;2883 const ais = r.ais;
2842 const token_tags = tree.tokens.items(.tag);2884 const token_tags = tree.tokens.items(.tag);
...@@ -2922,7 +2964,7 @@ fn hasMultilineString(tree: Ast, start_token: Ast.TokenIndex, end_token: Ast.Tok...@@ -2922,7 +2964,7 @@ fn hasMultilineString(tree: Ast, start_token: Ast.TokenIndex, end_token: Ast.Tok
29222964
2923/// Assumes that start is the first byte past the previous token and2965/// Assumes that start is the first byte past the previous token and
2924/// that end is the last byte before the next token.2966/// that end is the last byte before the next token.
2925fn renderComments(r: Render, start: usize, end: usize) Error!bool {2967fn renderComments(r: *Render, start: usize, end: usize) Error!bool {
2926 const tree = r.tree;2968 const tree = r.tree;
2927 const ais = r.ais;2969 const ais = r.ais;
29282970
...@@ -2985,12 +3027,12 @@ fn renderComments(r: Render, start: usize, end: usize) Error!bool {...@@ -2985,12 +3027,12 @@ fn renderComments(r: Render, start: usize, end: usize) Error!bool {
2985 return index != start;3027 return index != start;
2986}3028}
29873029
2988fn renderExtraNewline(r: Render, node: Ast.Node.Index) Error!void {3030fn renderExtraNewline(r: *Render, node: Ast.Node.Index) Error!void {
2989 return renderExtraNewlineToken(r, r.tree.firstToken(node));3031 return renderExtraNewlineToken(r, r.tree.firstToken(node));
2990}3032}
29913033
2992/// Check if there is an empty line immediately before the given token. If so, render it.3034/// Check if there is an empty line immediately before the given token. If so, render it.
2993fn renderExtraNewlineToken(r: Render, token_index: Ast.TokenIndex) Error!void {3035fn renderExtraNewlineToken(r: *Render, token_index: Ast.TokenIndex) Error!void {
2994 const tree = r.tree;3036 const tree = r.tree;
2995 const ais = r.ais;3037 const ais = r.ais;
2996 const token_starts = tree.tokens.items(.start);3038 const token_starts = tree.tokens.items(.start);
...@@ -3017,7 +3059,7 @@ fn renderExtraNewlineToken(r: Render, token_index: Ast.TokenIndex) Error!void {...@@ -3017,7 +3059,7 @@ fn renderExtraNewlineToken(r: Render, token_index: Ast.TokenIndex) Error!void {
30173059
3018/// end_token is the token one past the last doc comment token. This function3060/// end_token is the token one past the last doc comment token. This function
3019/// searches backwards from there.3061/// searches backwards from there.
3020fn renderDocComments(r: Render, end_token: Ast.TokenIndex) Error!void {3062fn renderDocComments(r: *Render, end_token: Ast.TokenIndex) Error!void {
3021 const tree = r.tree;3063 const tree = r.tree;
3022 // Search backwards for the first doc comment.3064 // Search backwards for the first doc comment.
3023 const token_tags = tree.tokens.items(.tag);3065 const token_tags = tree.tokens.items(.tag);
...@@ -3049,7 +3091,7 @@ fn renderDocComments(r: Render, end_token: Ast.TokenIndex) Error!void {...@@ -3049,7 +3091,7 @@ fn renderDocComments(r: Render, end_token: Ast.TokenIndex) Error!void {
3049}3091}
30503092
3051/// start_token is first container doc comment token.3093/// start_token is first container doc comment token.
3052fn renderContainerDocComments(r: Render, start_token: Ast.TokenIndex) Error!void {3094fn renderContainerDocComments(r: *Render, start_token: Ast.TokenIndex) Error!void {
3053 const tree = r.tree;3095 const tree = r.tree;
3054 const token_tags = tree.tokens.items(.tag);3096 const token_tags = tree.tokens.items(.tag);
3055 var tok = start_token;3097 var tok = start_token;
...@@ -3064,6 +3106,25 @@ fn renderContainerDocComments(r: Render, start_token: Ast.TokenIndex) Error!void...@@ -3064,6 +3106,25 @@ fn renderContainerDocComments(r: Render, start_token: Ast.TokenIndex) Error!void
3064 }3106 }
3065}3107}
30663108
3109fn discardAllParams(r: *Render, fn_proto_node: Ast.Node.Index) Error!void {
3110 const tree = r.tree;
3111 const ais = r.ais;
3112 var buf: [1]Ast.Node.Index = undefined;
3113 const fn_proto = tree.fullFnProto(&buf, fn_proto_node).?;
3114 const token_tags = tree.tokens.items(.tag);
3115 const main_tokens = tree.nodes.items(.main_token);
3116 for (fn_proto.ast.params) |param_node| {
3117 const type_ident = main_tokens[param_node];
3118 assert(token_tags[type_ident] == .identifier);
3119 const name_ident = type_ident - 2;
3120 assert(token_tags[name_ident] == .identifier);
3121 const w = ais.writer();
3122 try w.writeAll("_ = ");
3123 try w.writeAll(tokenSliceForRender(r.tree, name_ident));
3124 try w.writeAll(";\n");
3125 }
3126}
3127
3067fn tokenSliceForRender(tree: Ast, token_index: Ast.TokenIndex) []const u8 {3128fn tokenSliceForRender(tree: Ast, token_index: Ast.TokenIndex) []const u8 {
3068 var ret = tree.tokenSlice(token_index);3129 var ret = tree.tokenSlice(token_index);
3069 switch (tree.tokens.items(.tag)[token_index]) {3130 switch (tree.tokens.items(.tag)[token_index]) {
src/reduce.zig+17-1
...@@ -11,6 +11,15 @@ const Transformation = enum {...@@ -11,6 +11,15 @@ const Transformation = enum {
11 none,11 none,
12};12};
1313
14// Roadmap:
15// - add the main loop that checks for interestingness
16// - add transformations
17// - gut function
18// - replace body with `@trap();`
19// - discard the parameters
20// - add thread pool
21// - add support for `@import` detection and other files
22
14pub fn main(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {23pub fn main(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
15 const file_path = args[2];24 const file_path = args[2];
16 const transformation = std.meta.stringToEnum(Transformation, args[3]);25 const transformation = std.meta.stringToEnum(Transformation, args[3]);
...@@ -35,7 +44,14 @@ pub fn main(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {...@@ -35,7 +44,14 @@ pub fn main(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
35 var rendered = std.ArrayList(u8).init(gpa);44 var rendered = std.ArrayList(u8).init(gpa);
36 defer rendered.deinit();45 defer rendered.deinit();
37 rendered.clearRetainingCapacity();46 rendered.clearRetainingCapacity();
38 try tree.renderToArrayList(&rendered);47
48 var gut_functions: std.AutoHashMapUnmanaged(u32, void) = .{};
49 try gut_functions.put(arena, 1, {});
50 try gut_functions.put(arena, 3, {});
51
52 try tree.renderToArrayList(&rendered, .{
53 .gut_functions = gut_functions,
54 });
3955
40 const stdout = std.io.getStdOut();56 const stdout = std.io.getStdOut();
41 try stdout.writeAll(rendered.items);57 try stdout.writeAll(rendered.items);