@@ -69,6 +69,8 @@ pub fn generateZirData(self: *Autodoc) !void {
6969 }
7070 }
7171
72+ log .debug ("Ref map size: {}" , .{Ref .typed_value_map .len });
73+
7274 const root_src_dir = self .module .main_pkg .root_src_directory ;
7375 const root_src_path = self .module .main_pkg .root_src_path ;
7476 const joined_src_path = try root_src_dir .join (self .arena , &.{root_src_path });
@@ -159,6 +161,9 @@ pub fn generateZirData(self: *Autodoc) !void {
159161 .void_type = > .{
160162 .Void = .{ .name = tmpbuf .toOwnedSlice () },
161163 },
164+ .type_info_type = > .{
165+ .ComptimeExpr = .{ .name = tmpbuf .toOwnedSlice () },
166+ },
162167 .type_type = > .{
163168 .Type = .{ .name = tmpbuf .toOwnedSlice () },
164169 },
@@ -608,6 +613,7 @@ const DocData = struct {
608613 type : usize , // index in `types`
609614 this : usize , // index in `types`
610615 declRef : usize , // index in `decls`
616+ builtinField : enum { len , ptr },
611617 fieldRef : FieldRef ,
612618 refPath : []Expr ,
613619 int : struct {
@@ -697,20 +703,26 @@ const DocData = struct {
697703 var jsw = std .json .writeStream (w , 15 );
698704 try jsw .beginObject ();
699705 try jsw .objectField (@tagName (active_tag ));
700- inline for (comptime std .meta .fields (Expr )) | case | {
701- if (@field (Expr , case .name ) == active_tag ) {
702- switch (active_tag ) {
703- .int = > {
704- if (self .int .negated ) try w .writeAll ("-" );
705- try jsw .emitNumber (self .int .value );
706- },
707- .int_big = > {
706+ switch (self ) {
707+ .int = > {
708+ if (self .int .negated ) try w .writeAll ("-" );
709+ try jsw .emitNumber (self .int .value );
710+ },
711+ .int_big = > {
708712
709- //@panic("TODO: json serialization of big ints!");
710- //if (v.negated) try w.writeAll("-");
711- //try jsw.emitNumber(v.value);
712- },
713- else = > {
713+ //@panic("TODO: json serialization of big ints!");
714+ //if (v.negated) try w.writeAll("-");
715+ //try jsw.emitNumber(v.value);
716+ },
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 ) {
714726 try std .json .stringify (@field (self , case .name ), opt , w );
715727 jsw .state_index -= 1 ;
716728 // TODO: we should not reach into the state of the
@@ -719,9 +731,9 @@ const DocData = struct {
719731 // would be nice to have a proper integration
720732 // between the json writer and the generic
721733 // std.json.stringify implementation
722- },
734+ }
723735 }
724- }
736+ },
725737 }
726738 try jsw .endObject ();
727739 }
@@ -1905,31 +1917,60 @@ fn walkInstruction(
19051917 const extra = file .zir .extraData (Zir .Inst .Field , pl_node .payload_index );
19061918
19071919 var path : std .ArrayListUnmanaged (DocData .Expr ) = .{};
1908- var lhs = @enumToInt (extra .data .lhs ) - Ref .typed_value_map .len ; // underflow = need to handle Refs
1909-
19101920 try path .append (self .arena , .{
19111921 .string = file .zir .nullTerminatedString (extra .data .field_name_start ),
19121922 });
1923+
19131924 // Put inside path the starting index of each decl name that
1914- // we encounter as we navigate through all the field_vals
1915- while (tags [lhs ] == .field_val or
1916- tags [lhs ] == .field_call_bind or
1917- tags [lhs ] == .field_ptr or
1918- tags [lhs ] == .field_type )
1919- {
1920- const lhs_extra = file .zir .extraData (
1921- Zir .Inst .Field ,
1922- data [lhs ].pl_node .payload_index ,
1923- );
1925+ // we encounter as we navigate through all the field_*s
1926+ const lhs_ref = blk : {
1927+ var lhs_extra = extra ;
1928+ while (true ) {
1929+ if (@enumToInt (lhs_extra .data .lhs ) < Ref .typed_value_map .len ) {
1930+ break :blk lhs_extra .data .lhs ;
1931+ }
19241932
1925- try path .append (self .arena , .{
1926- .string = file .zir .nullTerminatedString (lhs_extra .data .field_name_start ),
1927- });
1928- lhs = @enumToInt (lhs_extra .data .lhs ) - Ref .typed_value_map .len ; // underflow = need to handle Refs
1929- }
1933+ const lhs = @enumToInt (lhs_extra .data .lhs ) - Ref .typed_value_map .len ;
1934+ if (tags [lhs ] != .field_val and
1935+ tags [lhs ] != .field_call_bind and
1936+ tags [lhs ] != .field_ptr and
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
1950+ // If the lhs is a `call` instruction, it means that we're inside
1951+ // a function call and we're referring to one of its arguments.
1952+ // We can't just blindly analyze the instruction or we will
1953+ // start recursing forever.
1954+ // TODO: add proper resolution of the container type for `calls`
1955+ // TODO: we're like testing lhs as an instruction twice
1956+ // (above and below) this todo, maybe a cleaer solution woul
1957+ // avoid that.
19311958 // TODO: double check that we really don't need type info here
1932- const wr = try self .walkInstruction (file , parent_scope , lhs , false );
1959+
1960+ const wr = blk : {
1961+ if (@enumToInt (lhs_ref ) >= Ref .typed_value_map .len ) {
1962+ const lhs_inst = @enumToInt (lhs_ref ) - Ref .typed_value_map .len ;
1963+ if (tags [lhs_inst ] == .call ) {
1964+ break :blk DocData.WalkResult {
1965+ .expr = .{
1966+ .comptimeExpr = 0 ,
1967+ },
1968+ };
1969+ }
1970+ }
1971+
1972+ break :blk try self .walkRef (file , parent_scope , lhs_ref , false );
1973+ };
19331974 try path .append (self .arena , wr .expr );
19341975
19351976 // This way the data in `path` has the same ordering that the ref
@@ -1948,7 +1989,7 @@ fn walkInstruction(
19481989 // - (2) Paths can sometimes never resolve fully. This means that
19491990 // any value that depends on that will have to become a
19501991 // comptimeExpr.
1951- try self .tryResolveRefPath (file , lhs , path .items );
1992+ try self .tryResolveRefPath (file , inst_index , path .items );
19521993 return DocData.WalkResult { .expr = .{ .refPath = path .items } };
19531994 },
19541995 .int_type = > {
@@ -2053,6 +2094,33 @@ fn walkInstruction(
20532094 );
20542095 return self .cteTodo (@tagName (tags [inst_index ]));
20552096 },
2097+ .struct_init_anon = > {
2098+ const pl_node = data [inst_index ].pl_node ;
2099+ const extra = file .zir .extraData (Zir .Inst .StructInitAnon , pl_node .payload_index );
2100+
2101+ const field_vals = try self .arena .alloc (
2102+ DocData .Expr .FieldVal ,
2103+ extra .data .fields_len ,
2104+ );
2105+
2106+ var idx = extra .end ;
2107+ for (field_vals ) | * fv | {
2108+ const init_extra = file .zir .extraData (Zir .Inst .StructInitAnon .Item , idx );
2109+ const field_name = file .zir .nullTerminatedString (init_extra .data .field_name );
2110+ const value = try self .walkRef (
2111+ file ,
2112+ parent_scope ,
2113+ init_extra .data .init ,
2114+ need_type ,
2115+ );
2116+ fv .* = .{ .name = field_name , .val = value };
2117+ idx = init_extra .end ;
2118+ }
2119+
2120+ return DocData.WalkResult {
2121+ .expr = .{ .@"struct" = field_vals },
2122+ };
2123+ },
20562124 .error_set_decl = > {
20572125 const pl_node = data [inst_index ].pl_node ;
20582126 const extra = file .zir .extraData (Zir .Inst .ErrorSetDecl , pl_node .payload_index );
@@ -3072,6 +3140,10 @@ fn tryResolveRefPath(
30723140 .{ @tagName (self .types .items [t_index ]), resolved_parent },
30733141 );
30743142 },
3143+ .ComptimeExpr = > {
3144+ // Same as the comptimeExpr branch above
3145+ break :outer ;
3146+ },
30753147 .Unanalyzed = > {
30763148 // This decl path is pending completion
30773149 {
@@ -3094,6 +3166,20 @@ fn tryResolveRefPath(
30943166
30953167 return ;
30963168 },
3169+ .Array = > {
3170+ if (std .mem .eql (u8 , child_string , "len" )) {
3171+ path [i + 1 ] = .{
3172+ .builtinField = .len ,
3173+ };
3174+ } else {
3175+ panicWithContext (
3176+ file ,
3177+ inst_index ,
3178+ "TODO: handle `{s}` in tryResolveDeclPath.type.Array\n Info: {}" ,
3179+ .{ child_string , resolved_parent },
3180+ );
3181+ }
3182+ },
30973183 .Enum = > | t_enum | {
30983184 for (t_enum .pubDecls ) | d | {
30993185 // TODO: this could be improved a lot
@@ -3820,9 +3906,12 @@ fn walkRef(
38203906 } else if (enum_value < Ref .typed_value_map .len ) {
38213907 switch (ref ) {
38223908 else = > {
3823- std .debug .panic ("TODO: handle {s} in `walkRef`\n " , .{
3824- @tagName (ref ),
3825- });
3909+ panicWithContext (
3910+ file ,
3911+ 0 ,
3912+ "TODO: handle {s} in walkRef" ,
3913+ .{@tagName (ref )},
3914+ );
38263915 },
38273916 .undef = > {
38283917 return DocData.WalkResult { .expr = .@"undefined" };
0 commit comments