authorgravatar for kappaloris@gmail.comLoris Cro <kappaloris@gmail.com> 2022-08-21 18:53:00+02:00
committergravatar for kappaloris@gmail.comLoris Cro <kappaloris@gmail.com> 2022-08-23 18:37:29+02:00
log0482e8ba9d63ea009a9e0c2d497371261764d3e1
tree3e92ac8a2a2da11a0bc301510bdefb87d5dd9723
parent583175dc1d8d14bc92838476eb226f0e91077abc

autodoc: initial support for struct_init_anon


2 files changed, 129 insertions(+), 48 deletions(-)

lib/docs/main.js+16-11
...@@ -1430,20 +1430,25 @@ var zigAnalysis;...@@ -1430,20 +1430,25 @@ var zigAnalysis;
1430 return lhs + "!" + rhs;1430 return lhs + "!" + rhs;
1431 }1431 }
1432 case "struct": {1432 case "struct": {
1433 const struct_name =1433 // const struct_name =
1434 zigAnalysis.decls[expr.struct[0].val.typeRef.refPath[0].declRef].name;1434 // zigAnalysis.decls[expr.struct[0].val.typeRef.refPath[0].declRef].name;
1435 const struct_name = ".";
1435 let struct_body = "";1436 let struct_body = "";
1436 struct_body += struct_name + "{ ";1437 struct_body += struct_name + "{ ";
1437 for (let i = 0; i < expr.struct.length; i++) {1438 for (let i = 0; i < expr.struct.length; i++) {
1438 const val = expr.struct[i].name;1439 const fv = expr.struct[i];
1439 const exprArg = zigAnalysis.exprs[expr.struct[i].val.expr.as.exprArg];1440 const field_name = fv.name;
1440 let value_field = exprArg[Object.keys(exprArg)[0]];1441 const exprArg = zigAnalysis.exprs[fv.val.expr.as.exprArg];
1441 if (value_field instanceof Object) {1442 let field_value = exprName(exprArg, opts);
1442 value_field =1443 // TODO: commented out because it seems not needed. if it deals
1443 zigAnalysis.decls[value_field[0].val.typeRef.refPath[0].declRef]1444 // with a corner case, please add a comment when re-enabling it.
1444 .name;1445 // let field_value = exprArg[Object.keys(exprArg)[0]];
1445 }1446 // if (field_value instanceof Object) {
1446 struct_body += "." + val + " = " + value_field;1447 // value_field = exprName(value_field)
1448 // zigAnalysis.decls[value_field[0].val.typeRef.refPath[0].declRef]
1449 // .name;
1450 // }
1451 struct_body += "." + field_name + " = " + field_value;
1447 if (i !== expr.struct.length - 1) {1452 if (i !== expr.struct.length - 1) {
1448 struct_body += ", ";1453 struct_body += ", ";
1449 } else {1454 } else {
src/Autodoc.zig+113-37
...@@ -69,6 +69,8 @@ pub fn generateZirData(self: *Autodoc) !void {...@@ -69,6 +69,8 @@ pub fn generateZirData(self: *Autodoc) !void {
69 }69 }
70 }70 }
7171
72 log.debug("Ref map size: {}", .{Ref.typed_value_map.len});
73
72 const root_src_dir = self.module.main_pkg.root_src_directory;74 const root_src_dir = self.module.main_pkg.root_src_directory;
73 const root_src_path = self.module.main_pkg.root_src_path;75 const root_src_path = self.module.main_pkg.root_src_path;
74 const joined_src_path = try root_src_dir.join(self.arena, &.{root_src_path});76 const joined_src_path = try root_src_dir.join(self.arena, &.{root_src_path});
...@@ -159,6 +161,9 @@ pub fn generateZirData(self: *Autodoc) !void {...@@ -159,6 +161,9 @@ pub fn generateZirData(self: *Autodoc) !void {
159 .void_type => .{161 .void_type => .{
160 .Void = .{ .name = tmpbuf.toOwnedSlice() },162 .Void = .{ .name = tmpbuf.toOwnedSlice() },
161 },163 },
164 .type_info_type => .{
165 .Unanalyzed = .{},
166 },
162 .type_type => .{167 .type_type => .{
163 .Type = .{ .name = tmpbuf.toOwnedSlice() },168 .Type = .{ .name = tmpbuf.toOwnedSlice() },
164 },169 },
...@@ -608,6 +613,7 @@ const DocData = struct {...@@ -608,6 +613,7 @@ const DocData = struct {
608 type: usize, // index in `types`613 type: usize, // index in `types`
609 this: usize, // index in `types`614 this: usize, // index in `types`
610 declRef: usize, // index in `decls`615 declRef: usize, // index in `decls`
616 builtinField: enum { len, ptr },
611 fieldRef: FieldRef,617 fieldRef: FieldRef,
612 refPath: []Expr,618 refPath: []Expr,
613 int: struct {619 int: struct {
...@@ -697,20 +703,26 @@ const DocData = struct {...@@ -697,20 +703,26 @@ const DocData = struct {
697 var jsw = std.json.writeStream(w, 15);703 var jsw = std.json.writeStream(w, 15);
698 try jsw.beginObject();704 try jsw.beginObject();
699 try jsw.objectField(@tagName(active_tag));705 try jsw.objectField(@tagName(active_tag));
700 inline for (comptime std.meta.fields(Expr)) |case| {706 switch (self) {
701 if (@field(Expr, case.name) == active_tag) {707 .int => {
702 switch (active_tag) {708 if (self.int.negated) try w.writeAll("-");
703 .int => {709 try jsw.emitNumber(self.int.value);
704 if (self.int.negated) try w.writeAll("-");710 },
705 try jsw.emitNumber(self.int.value);711 .int_big => {
706 },
707 .int_big => {
708712
709 //@panic("TODO: json serialization of big ints!");713 //@panic("TODO: json serialization of big ints!");
710 //if (v.negated) try w.writeAll("-");714 //if (v.negated) try w.writeAll("-");
711 //try jsw.emitNumber(v.value);715 //try jsw.emitNumber(v.value);
712 },716 },
713 else => {717 .builtinField => {
718 try jsw.emitString(@tagName(self.builtinField));
719 },
720 else => {
721 inline for (comptime std.meta.fields(Expr)) |case| {
722 // TODO: this is super ugly, fix once `inline else` is a thing
723 if (comptime std.mem.eql(u8, case.name, "builtinField"))
724 continue;
725 if (@field(Expr, case.name) == active_tag) {
714 try std.json.stringify(@field(self, case.name), opt, w);726 try std.json.stringify(@field(self, case.name), opt, w);
715 jsw.state_index -= 1;727 jsw.state_index -= 1;
716 // TODO: we should not reach into the state of the728 // TODO: we should not reach into the state of the
...@@ -719,9 +731,9 @@ const DocData = struct {...@@ -719,9 +731,9 @@ const DocData = struct {
719 // would be nice to have a proper integration731 // would be nice to have a proper integration
720 // between the json writer and the generic732 // between the json writer and the generic
721 // std.json.stringify implementation733 // std.json.stringify implementation
722 },734 }
723 }735 }
724 }736 },
725 }737 }
726 try jsw.endObject();738 try jsw.endObject();
727 }739 }
...@@ -1905,31 +1917,38 @@ fn walkInstruction(...@@ -1905,31 +1917,38 @@ fn walkInstruction(
1905 const extra = file.zir.extraData(Zir.Inst.Field, pl_node.payload_index);1917 const extra = file.zir.extraData(Zir.Inst.Field, pl_node.payload_index);
19061918
1907 var path: std.ArrayListUnmanaged(DocData.Expr) = .{};1919 var path: std.ArrayListUnmanaged(DocData.Expr) = .{};
1908 var lhs = @enumToInt(extra.data.lhs) - Ref.typed_value_map.len; // underflow = need to handle Refs
1909
1910 try path.append(self.arena, .{1920 try path.append(self.arena, .{
1911 .string = file.zir.nullTerminatedString(extra.data.field_name_start),1921 .string = file.zir.nullTerminatedString(extra.data.field_name_start),
1912 });1922 });
1923
1913 // Put inside path the starting index of each decl name that1924 // Put inside path the starting index of each decl name that
1914 // we encounter as we navigate through all the field_vals1925 // we encounter as we navigate through all the field_*s
1915 while (tags[lhs] == .field_val or1926 const lhs_ref = blk: {
1916 tags[lhs] == .field_call_bind or1927 var lhs_extra = extra;
1917 tags[lhs] == .field_ptr or1928 while (true) {
1918 tags[lhs] == .field_type)1929 if (@enumToInt(lhs_extra.data.lhs) < Ref.typed_value_map.len) {
1919 {1930 break :blk lhs_extra.data.lhs;
1920 const lhs_extra = file.zir.extraData(1931 }
1921 Zir.Inst.Field,
1922 data[lhs].pl_node.payload_index,
1923 );
19241932
1925 try path.append(self.arena, .{1933 const lhs = @enumToInt(lhs_extra.data.lhs) - Ref.typed_value_map.len;
1926 .string = file.zir.nullTerminatedString(lhs_extra.data.field_name_start),1934 if (tags[lhs] != .field_val and
1927 });1935 tags[lhs] != .field_call_bind and
1928 lhs = @enumToInt(lhs_extra.data.lhs) - Ref.typed_value_map.len; // underflow = need to handle Refs1936 tags[lhs] != .field_ptr and
1929 }1937 tags[lhs] != .field_type) break :blk lhs_extra.data.lhs;
1938
1939 lhs_extra = file.zir.extraData(
1940 Zir.Inst.Field,
1941 data[lhs].pl_node.payload_index,
1942 );
1943
1944 try path.append(self.arena, .{
1945 .string = file.zir.nullTerminatedString(lhs_extra.data.field_name_start),
1946 });
1947 }
1948 };
19301949
1931 // TODO: double check that we really don't need type info here1950 // TODO: double check that we really don't need type info here
1932 const wr = try self.walkInstruction(file, parent_scope, lhs, false);1951 const wr = try self.walkRef(file, parent_scope, lhs_ref, false);
1933 try path.append(self.arena, wr.expr);1952 try path.append(self.arena, wr.expr);
19341953
1935 // This way the data in `path` has the same ordering that the ref1954 // This way the data in `path` has the same ordering that the ref
...@@ -1948,7 +1967,7 @@ fn walkInstruction(...@@ -1948,7 +1967,7 @@ fn walkInstruction(
1948 // - (2) Paths can sometimes never resolve fully. This means that1967 // - (2) Paths can sometimes never resolve fully. This means that
1949 // any value that depends on that will have to become a1968 // any value that depends on that will have to become a
1950 // comptimeExpr.1969 // comptimeExpr.
1951 try self.tryResolveRefPath(file, lhs, path.items);1970 try self.tryResolveRefPath(file, inst_index, path.items);
1952 return DocData.WalkResult{ .expr = .{ .refPath = path.items } };1971 return DocData.WalkResult{ .expr = .{ .refPath = path.items } };
1953 },1972 },
1954 .int_type => {1973 .int_type => {
...@@ -2053,6 +2072,46 @@ fn walkInstruction(...@@ -2053,6 +2072,46 @@ fn walkInstruction(
2053 );2072 );
2054 return self.cteTodo(@tagName(tags[inst_index]));2073 return self.cteTodo(@tagName(tags[inst_index]));
2055 },2074 },
2075 .struct_init_anon => {
2076 const pl_node = data[inst_index].pl_node;
2077 const extra = file.zir.extraData(Zir.Inst.StructInitAnon, pl_node.payload_index);
2078
2079 const field_vals = try self.arena.alloc(
2080 DocData.Expr.FieldVal,
2081 extra.data.fields_len,
2082 );
2083
2084 log.debug("number of fields: {}", .{extra.data.fields_len});
2085 var idx = extra.end;
2086 for (field_vals) |*fv| {
2087 const init_extra = file.zir.extraData(Zir.Inst.StructInitAnon.Item, idx);
2088 const field_name = file.zir.nullTerminatedString(init_extra.data.field_name);
2089 fv.* = .{
2090 .name = field_name,
2091 .val = DocData.WalkResult{
2092 .expr = .{ .comptimeExpr = 0 },
2093 },
2094 };
2095 // printWithContext(
2096 // file,
2097 // inst_index,
2098 // "analyzing field [{}] %{} `{s}`",
2099 // .{ i, init_extra.data.init, field_name },
2100 // );
2101 // const value = try self.walkRef(
2102 // file,
2103 // parent_scope,
2104 // init_extra.data.init,
2105 // need_type,
2106 // );
2107 // fv.* = .{ .name = field_name, .val = value };
2108 // idx = init_extra.end;
2109 }
2110
2111 return DocData.WalkResult{
2112 .expr = .{ .@"struct" = field_vals },
2113 };
2114 },
2056 .error_set_decl => {2115 .error_set_decl => {
2057 const pl_node = data[inst_index].pl_node;2116 const pl_node = data[inst_index].pl_node;
2058 const extra = file.zir.extraData(Zir.Inst.ErrorSetDecl, pl_node.payload_index);2117 const extra = file.zir.extraData(Zir.Inst.ErrorSetDecl, pl_node.payload_index);
...@@ -3094,6 +3153,20 @@ fn tryResolveRefPath(...@@ -3094,6 +3153,20 @@ fn tryResolveRefPath(
30943153
3095 return;3154 return;
3096 },3155 },
3156 .Array => {
3157 if (std.mem.eql(u8, child_string, "len")) {
3158 path[i + 1] = .{
3159 .builtinField = .len,
3160 };
3161 } else {
3162 panicWithContext(
3163 file,
3164 inst_index,
3165 "TODO: handle `{s}` in tryResolveDeclPath.type.Array\nInfo: {}",
3166 .{ child_string, resolved_parent },
3167 );
3168 }
3169 },
3097 .Enum => |t_enum| {3170 .Enum => |t_enum| {
3098 for (t_enum.pubDecls) |d| {3171 for (t_enum.pubDecls) |d| {
3099 // TODO: this could be improved a lot3172 // TODO: this could be improved a lot
...@@ -3820,9 +3893,12 @@ fn walkRef(...@@ -3820,9 +3893,12 @@ fn walkRef(
3820 } else if (enum_value < Ref.typed_value_map.len) {3893 } else if (enum_value < Ref.typed_value_map.len) {
3821 switch (ref) {3894 switch (ref) {
3822 else => {3895 else => {
3823 std.debug.panic("TODO: handle {s} in `walkRef`\n", .{3896 panicWithContext(
3824 @tagName(ref),3897 file,
3825 });3898 0,
3899 "TODO: handle {s} in walkRef",
3900 .{@tagName(ref)},
3901 );
3826 },3902 },
3827 .undef => {3903 .undef => {
3828 return DocData.WalkResult{ .expr = .@"undefined" };3904 return DocData.WalkResult{ .expr = .@"undefined" };