| ... | ... | @@ -411,17 +411,17 @@ const DocData = struct { |
| 411 | 411 | }, |
| 412 | 412 | Enum: struct { |
| 413 | 413 | name: []const u8, |
| 414 | | src: ?usize = null, // index into astNodes |
| 415 | | privDecls: ?[]usize = null, // index into decls |
| 416 | | pubDecls: ?[]usize = null, // index into decls |
| 414 | src: usize, // index into astNodes |
| 415 | privDecls: []usize = &.{}, // index into decls |
| 416 | pubDecls: []usize = &.{}, // index into decls |
| 417 | 417 | // (use src->fields to find field names) |
| 418 | 418 | }, |
| 419 | 419 | Union: struct { |
| 420 | 420 | name: []const u8, |
| 421 | | src: ?usize = null, // index into astNodes |
| 422 | | privDecls: ?[]usize = null, // index into decls |
| 423 | | pubDecls: ?[]usize = null, // index into decls |
| 424 | | fields: ?[]WalkResult = null, // (use src->fields to find names) |
| 421 | src: usize, // index into astNodes |
| 422 | privDecls: []usize = &.{}, // index into decls |
| 423 | pubDecls: []usize = &.{}, // index into decls |
| 424 | fields: []WalkResult = &.{}, // (use src->fields to find names) |
| 425 | 425 | }, |
| 426 | 426 | Fn: struct { |
| 427 | 427 | name: []const u8, |
| ... | ... | @@ -465,6 +465,7 @@ const DocData = struct { |
| 465 | 465 | .Struct => |v| try printTypeBody(v, options, w), |
| 466 | 466 | .Fn => |v| try printTypeBody(v, options, w), |
| 467 | 467 | .Union => |v| try printTypeBody(v, options, w), |
| 468 | .ErrorSet => |v| try printTypeBody(v, options, w), |
| 468 | 469 | .Enum => |v| try printTypeBody(v, options, w), |
| 469 | 470 | .Int => |v| try printTypeBody(v, options, w), |
| 470 | 471 | .Float => |v| try printTypeBody(v, options, w), |
| ... | ... | @@ -604,8 +605,12 @@ const DocData = struct { |
| 604 | 605 | , .{}); |
| 605 | 606 | try v.typeRef.jsonStringify(options, w); |
| 606 | 607 | try w.print( |
| 607 | | \\, "value": {s}{} }} }} |
| 608 | | , .{ neg, v.value }); |
| 608 | \\, "value": {s}1 }} }} |
| 609 | , .{neg}); |
| 610 | // TODO: uncomment once float panic is fixed in stdlib |
| 611 | // try w.print( |
| 612 | // \\, "value": {s}{e} }} }} |
| 613 | // , .{ neg, v.value }); |
| 609 | 614 | }, |
| 610 | 615 | .bool => |v| { |
| 611 | 616 | try w.print( |
| ... | ... | @@ -685,12 +690,13 @@ fn walkInstruction( |
| 685 | 690 | |
| 686 | 691 | switch (tags[inst_index]) { |
| 687 | 692 | else => { |
| 688 | | panicWithContext( |
| 693 | printWithContext( |
| 689 | 694 | file, |
| 690 | 695 | inst_index, |
| 691 | 696 | "TODO: implement `{s}` for walkInstruction\n\n", |
| 692 | 697 | .{@tagName(tags[inst_index])}, |
| 693 | 698 | ); |
| 699 | return self.cteTodo(@tagName(tags[inst_index])); |
| 694 | 700 | }, |
| 695 | 701 | .closure_get => { |
| 696 | 702 | const inst_node = data[inst_index].inst_node; |
| ... | ... | @@ -752,17 +758,11 @@ fn walkInstruction( |
| 752 | 758 | |
| 753 | 759 | return DocData.WalkResult{ .compileError = operand.string }; |
| 754 | 760 | }, |
| 755 | | .switch_block => return self.cteTodo("[switch]"), |
| 756 | 761 | .enum_literal => { |
| 757 | 762 | const str_tok = data[inst_index].str_tok; |
| 758 | 763 | const literal = file.zir.nullTerminatedString(str_tok.start); |
| 759 | 764 | return DocData.WalkResult{ .enumLiteral = literal }; |
| 760 | 765 | }, |
| 761 | | .div_exact, .div => return self.cteTodo("@div(...)"), |
| 762 | | .mul => return self.cteTodo("@mul(...)"), |
| 763 | | .array_mul => return self.cteTodo("a ** b"), |
| 764 | | .bool_br_and, .bool_br_or => return self.cteTodo("bool op"), |
| 765 | | .cmp_eq => return self.cteTodo("bool op"), |
| 766 | 766 | .int => { |
| 767 | 767 | const int = data[inst_index].int; |
| 768 | 768 | const t = try self.arena.create(DocData.WalkResult); |
| ... | ... | @@ -849,7 +849,7 @@ fn walkInstruction( |
| 849 | 849 | .negated = false, |
| 850 | 850 | }, |
| 851 | 851 | }, |
| 852 | | .child = typeOfWalkResult(array_data[0]), |
| 852 | .child = try self.typeOfWalkResult(array_data[0]), |
| 853 | 853 | }, |
| 854 | 854 | }); |
| 855 | 855 | |
| ... | ... | @@ -880,7 +880,17 @@ fn walkInstruction( |
| 880 | 880 | parent_scope, |
| 881 | 881 | un_node.operand, |
| 882 | 882 | ); |
| 883 | | operand.int.negated = true; // only support ints for now |
| 883 | switch (operand) { |
| 884 | .int => |*int| int.negated = true, |
| 885 | else => { |
| 886 | printWithContext( |
| 887 | file, |
| 888 | inst_index, |
| 889 | "TODO: support negation for more types", |
| 890 | .{}, |
| 891 | ); |
| 892 | }, |
| 893 | } |
| 884 | 894 | return operand; |
| 885 | 895 | }, |
| 886 | 896 | .size_of => { |
| ... | ... | @@ -913,21 +923,19 @@ fn walkInstruction( |
| 913 | 923 | var operand = try self.walkRef(file, parent_scope, extra.data.operand); |
| 914 | 924 | |
| 915 | 925 | switch (operand) { |
| 916 | | else => panicWithContext( |
| 926 | else => printWithContext( |
| 917 | 927 | file, |
| 918 | 928 | inst_index, |
| 919 | | "TODO: handle {s} in `walkInstruction.as_node`\n", |
| 929 | "TODO: handle {s} in `walkInstruction.as_node`", |
| 920 | 930 | .{@tagName(operand)}, |
| 921 | 931 | ), |
| 922 | | .refPath, .type, .string, .call, .enumLiteral => {}, |
| 932 | .declRef, .refPath, .type, .string, .call, .enumLiteral => {}, |
| 923 | 933 | // we don't do anything because up until now, |
| 924 | 934 | // I've only seen this used as such: |
| 925 | 935 | // @as(@as(type, Baz), .{}) |
| 926 | 936 | // and we don't want to toss away the |
| 927 | 937 | // decl_val information (eg by replacing it with |
| 928 | 938 | // a WalkResult.type). |
| 929 | | // TODO: Actually, this is a good moment to check if |
| 930 | | // the result is indeed a type!! |
| 931 | 939 | .comptimeExpr => { |
| 932 | 940 | self.comptime_exprs.items[operand.comptimeExpr].typeRef = dest_type_ref; |
| 933 | 941 | }, |
| ... | ... | @@ -1043,7 +1051,7 @@ fn walkInstruction( |
| 1043 | 1051 | var idx = extra.end; |
| 1044 | 1052 | for (field_vals) |*fv| { |
| 1045 | 1053 | const init_extra = file.zir.extraData(Zir.Inst.StructInit.Item, idx); |
| 1046 | | idx = init_extra.end; |
| 1054 | defer idx = init_extra.end; |
| 1047 | 1055 | |
| 1048 | 1056 | const field_name = blk: { |
| 1049 | 1057 | const field_inst_index = init_extra.data.field_type; |
| ... | ... | @@ -1176,53 +1184,45 @@ fn walkInstruction( |
| 1176 | 1184 | ); |
| 1177 | 1185 | }, |
| 1178 | 1186 | .extended => { |
| 1179 | | // NOTE: this code + the subsequent defer block are working towards |
| 1180 | | // solving pending decl paths that depend on completing the analysis of a type. |
| 1181 | | // When we don't find a type, the defer will run anyway but shouldn't |
| 1182 | | // ever be able to find a match inside `decl_paths_pending_on_types` |
| 1183 | | // TODO: extract this logic into a function and only call it when appropriate. |
| 1184 | | const type_slot_index = self.types.items.len; |
| 1185 | | try self.types.append(self.arena, .{ .Unanalyzed = {} }); |
| 1186 | | |
| 1187 | | defer { |
| 1188 | | if (self.ref_paths_pending_on_types.get(type_slot_index)) |paths| { |
| 1189 | | for (paths.items) |resume_info| { |
| 1190 | | self.tryResolveRefPath( |
| 1191 | | resume_info.file, |
| 1192 | | inst_index, |
| 1193 | | resume_info.ref_path, |
| 1194 | | ) catch { |
| 1195 | | @panic("Out of memory"); |
| 1196 | | }; |
| 1197 | | } |
| 1198 | | |
| 1199 | | _ = self.ref_paths_pending_on_types.remove(type_slot_index); |
| 1200 | | // TODO: we should deallocate the arraylist that holds all the |
| 1201 | | // decl paths. not doing it now since it's arena-allocated |
| 1202 | | // anyway, but maybe we should put it elsewhere. |
| 1203 | | } |
| 1204 | | } |
| 1205 | | |
| 1206 | 1187 | const extended = data[inst_index].extended; |
| 1207 | 1188 | switch (extended.opcode) { |
| 1208 | 1189 | else => { |
| 1209 | | panicWithContext( |
| 1190 | printWithContext( |
| 1210 | 1191 | file, |
| 1211 | 1192 | inst_index, |
| 1212 | | "TODO: implement `walkInstruction.extended` for {s}\n\n", |
| 1193 | "TODO: implement `walkInstruction.extended` for {s}", |
| 1213 | 1194 | .{@tagName(extended.opcode)}, |
| 1214 | 1195 | ); |
| 1196 | return self.cteTodo(@tagName(extended.opcode)); |
| 1215 | 1197 | }, |
| 1216 | 1198 | |
| 1217 | 1199 | .opaque_decl => return self.cteTodo("opaque {...}"), |
| 1218 | 1200 | .func => { |
| 1219 | | return try self.analyzeFunction( |
| 1201 | const type_slot_index = self.types.items.len; |
| 1202 | try self.types.append(self.arena, .{ .Unanalyzed = {} }); |
| 1203 | |
| 1204 | const result = try self.analyzeFunction( |
| 1220 | 1205 | file, |
| 1221 | 1206 | parent_scope, |
| 1222 | 1207 | inst_index, |
| 1223 | 1208 | self_ast_node_index, |
| 1224 | 1209 | type_slot_index, |
| 1225 | 1210 | ); |
| 1211 | if (self.ref_paths_pending_on_types.get(type_slot_index)) |paths| { |
| 1212 | for (paths.items) |resume_info| { |
| 1213 | try self.tryResolveRefPath( |
| 1214 | resume_info.file, |
| 1215 | inst_index, |
| 1216 | resume_info.ref_path, |
| 1217 | ); |
| 1218 | } |
| 1219 | |
| 1220 | _ = self.ref_paths_pending_on_types.remove(type_slot_index); |
| 1221 | // TODO: we should deallocate the arraylist that holds all the |
| 1222 | // decl paths. not doing it now since it's arena-allocated |
| 1223 | // anyway, but maybe we should put it elsewhere. |
| 1224 | } |
| 1225 | return result; |
| 1226 | 1226 | }, |
| 1227 | 1227 | .variable => { |
| 1228 | 1228 | const small = @bitCast(Zir.Inst.ExtendedVar.Small, extended.small); |
| ... | ... | @@ -1237,6 +1237,9 @@ fn walkInstruction( |
| 1237 | 1237 | return value; |
| 1238 | 1238 | }, |
| 1239 | 1239 | .union_decl => { |
| 1240 | const type_slot_index = self.types.items.len; |
| 1241 | try self.types.append(self.arena, .{ .Unanalyzed = {} }); |
| 1242 | |
| 1240 | 1243 | var scope: Scope = .{ |
| 1241 | 1244 | .parent = parent_scope, |
| 1242 | 1245 | .enclosing_type = type_slot_index, |
| ... | ... | @@ -1340,9 +1343,27 @@ fn walkInstruction( |
| 1340 | 1343 | }, |
| 1341 | 1344 | }; |
| 1342 | 1345 | |
| 1346 | if (self.ref_paths_pending_on_types.get(type_slot_index)) |paths| { |
| 1347 | for (paths.items) |resume_info| { |
| 1348 | try self.tryResolveRefPath( |
| 1349 | resume_info.file, |
| 1350 | inst_index, |
| 1351 | resume_info.ref_path, |
| 1352 | ); |
| 1353 | } |
| 1354 | |
| 1355 | _ = self.ref_paths_pending_on_types.remove(type_slot_index); |
| 1356 | // TODO: we should deallocate the arraylist that holds all the |
| 1357 | // decl paths. not doing it now since it's arena-allocated |
| 1358 | // anyway, but maybe we should put it elsewhere. |
| 1359 | } |
| 1360 | |
| 1343 | 1361 | return DocData.WalkResult{ .type = type_slot_index }; |
| 1344 | 1362 | }, |
| 1345 | 1363 | .enum_decl => { |
| 1364 | const type_slot_index = self.types.items.len; |
| 1365 | try self.types.append(self.arena, .{ .Unanalyzed = {} }); |
| 1366 | |
| 1346 | 1367 | var scope: Scope = .{ |
| 1347 | 1368 | .parent = parent_scope, |
| 1348 | 1369 | .enclosing_type = type_slot_index, |
| ... | ... | @@ -1470,10 +1491,27 @@ fn walkInstruction( |
| 1470 | 1491 | .pubDecls = decl_indexes.items, |
| 1471 | 1492 | }, |
| 1472 | 1493 | }; |
| 1494 | if (self.ref_paths_pending_on_types.get(type_slot_index)) |paths| { |
| 1495 | for (paths.items) |resume_info| { |
| 1496 | try self.tryResolveRefPath( |
| 1497 | resume_info.file, |
| 1498 | inst_index, |
| 1499 | resume_info.ref_path, |
| 1500 | ); |
| 1501 | } |
| 1502 | |
| 1503 | _ = self.ref_paths_pending_on_types.remove(type_slot_index); |
| 1504 | // TODO: we should deallocate the arraylist that holds all the |
| 1505 | // decl paths. not doing it now since it's arena-allocated |
| 1506 | // anyway, but maybe we should put it elsewhere. |
| 1507 | } |
| 1473 | 1508 | |
| 1474 | 1509 | return DocData.WalkResult{ .type = type_slot_index }; |
| 1475 | 1510 | }, |
| 1476 | 1511 | .struct_decl => { |
| 1512 | const type_slot_index = self.types.items.len; |
| 1513 | try self.types.append(self.arena, .{ .Unanalyzed = {} }); |
| 1514 | |
| 1477 | 1515 | var scope: Scope = .{ |
| 1478 | 1516 | .parent = parent_scope, |
| 1479 | 1517 | .enclosing_type = type_slot_index, |
| ... | ... | @@ -1563,6 +1601,20 @@ fn walkInstruction( |
| 1563 | 1601 | .fields = field_type_refs.items, |
| 1564 | 1602 | }, |
| 1565 | 1603 | }; |
| 1604 | if (self.ref_paths_pending_on_types.get(type_slot_index)) |paths| { |
| 1605 | for (paths.items) |resume_info| { |
| 1606 | try self.tryResolveRefPath( |
| 1607 | resume_info.file, |
| 1608 | inst_index, |
| 1609 | resume_info.ref_path, |
| 1610 | ); |
| 1611 | } |
| 1612 | |
| 1613 | _ = self.ref_paths_pending_on_types.remove(type_slot_index); |
| 1614 | // TODO: we should deallocate the arraylist that holds all the |
| 1615 | // decl paths. not doing it now since it's arena-allocated |
| 1616 | // anyway, but maybe we should put it elsewhere. |
| 1617 | } |
| 1566 | 1618 | |
| 1567 | 1619 | return DocData.WalkResult{ .type = type_slot_index }; |
| 1568 | 1620 | }, |
| ... | ... | @@ -1608,9 +1660,9 @@ fn walkDecls( |
| 1608 | 1660 | cur_bit_bag >>= 1; |
| 1609 | 1661 | const is_exported = @truncate(u1, cur_bit_bag) != 0; |
| 1610 | 1662 | cur_bit_bag >>= 1; |
| 1611 | | // const has_align = @truncate(u1, cur_bit_bag) != 0; |
| 1663 | const has_align = @truncate(u1, cur_bit_bag) != 0; |
| 1612 | 1664 | cur_bit_bag >>= 1; |
| 1613 | | // const has_section_or_addrspace = @truncate(u1, cur_bit_bag) != 0; |
| 1665 | const has_section_or_addrspace = @truncate(u1, cur_bit_bag) != 0; |
| 1614 | 1666 | cur_bit_bag >>= 1; |
| 1615 | 1667 | |
| 1616 | 1668 | // const sub_index = extra_index; |
| ... | ... | @@ -1626,21 +1678,26 @@ fn walkDecls( |
| 1626 | 1678 | const doc_comment_index = file.zir.extra[extra_index]; |
| 1627 | 1679 | extra_index += 1; |
| 1628 | 1680 | |
| 1629 | | // const align_inst: Zir.Inst.Ref = if (!has_align) .none else inst: { |
| 1630 | | // const inst = @intToEnum(Zir.Inst.Ref, file.zir.extra[extra_index]); |
| 1631 | | // extra_index += 1; |
| 1632 | | // break :inst inst; |
| 1633 | | // }; |
| 1634 | | // const section_inst: Zir.Inst.Ref = if (!has_section_or_addrspace) .none else inst: { |
| 1635 | | // const inst = @intToEnum(Zir.Inst.Ref, file.zir.extra[extra_index]); |
| 1636 | | // extra_index += 1; |
| 1637 | | // break :inst inst; |
| 1638 | | // }; |
| 1639 | | // const addrspace_inst: Zir.Inst.Ref = if (!has_section_or_addrspace) .none else inst: { |
| 1640 | | // const inst = @intToEnum(Zir.Inst.Ref, file.zir.extra[extra_index]); |
| 1641 | | // extra_index += 1; |
| 1642 | | // break :inst inst; |
| 1643 | | // }; |
| 1681 | const align_inst: Zir.Inst.Ref = if (!has_align) .none else inst: { |
| 1682 | const inst = @intToEnum(Zir.Inst.Ref, file.zir.extra[extra_index]); |
| 1683 | extra_index += 1; |
| 1684 | break :inst inst; |
| 1685 | }; |
| 1686 | _ = align_inst; |
| 1687 | |
| 1688 | const section_inst: Zir.Inst.Ref = if (!has_section_or_addrspace) .none else inst: { |
| 1689 | const inst = @intToEnum(Zir.Inst.Ref, file.zir.extra[extra_index]); |
| 1690 | extra_index += 1; |
| 1691 | break :inst inst; |
| 1692 | }; |
| 1693 | _ = section_inst; |
| 1694 | |
| 1695 | const addrspace_inst: Zir.Inst.Ref = if (!has_section_or_addrspace) .none else inst: { |
| 1696 | const inst = @intToEnum(Zir.Inst.Ref, file.zir.extra[extra_index]); |
| 1697 | extra_index += 1; |
| 1698 | break :inst inst; |
| 1699 | }; |
| 1700 | _ = addrspace_inst; |
| 1644 | 1701 | |
| 1645 | 1702 | // const pub_str = if (is_pub) "pub " else ""; |
| 1646 | 1703 | // const hash_bytes = @bitCast([16]u8, hash_u32s.*); |
| ... | ... | @@ -1848,6 +1905,7 @@ fn tryResolveRefPath( |
| 1848 | 1905 | while (j < 10_000) : (j += 1) { |
| 1849 | 1906 | switch (resolved_parent) { |
| 1850 | 1907 | else => break, |
| 1908 | .this => |t| resolved_parent = .{ .type = t }, |
| 1851 | 1909 | .declRef => |decl_index| { |
| 1852 | 1910 | const decl = self.decls.items[decl_index]; |
| 1853 | 1911 | if (decl._analyzed) { |
| ... | ... | @@ -1927,12 +1985,14 @@ fn tryResolveRefPath( |
| 1927 | 1985 | else => { |
| 1928 | 1986 | // NOTE: indirect references to types / decls should be handled |
| 1929 | 1987 | // in the switch above this one! |
| 1930 | | panicWithContext( |
| 1988 | printWithContext( |
| 1931 | 1989 | file, |
| 1932 | 1990 | inst_index, |
| 1933 | 1991 | "TODO: handle `{s}`in tryResolveRefPath\nInfo: {}", |
| 1934 | 1992 | .{ @tagName(resolved_parent), resolved_parent }, |
| 1935 | 1993 | ); |
| 1994 | path[i + 1] = try self.cteTodo("match failure"); |
| 1995 | continue :outer; |
| 1936 | 1996 | }, |
| 1937 | 1997 | .comptimeExpr, .call => { |
| 1938 | 1998 | // Since we hit a cte, we leave the remaining strings unresolved |
| ... | ... | @@ -1971,15 +2031,106 @@ fn tryResolveRefPath( |
| 1971 | 2031 | |
| 1972 | 2032 | return; |
| 1973 | 2033 | }, |
| 2034 | .Enum => |t_enum| { |
| 2035 | for (t_enum.pubDecls) |d| { |
| 2036 | // TODO: this could be improved a lot |
| 2037 | // by having our own string table! |
| 2038 | const decl = self.decls.items[d]; |
| 2039 | if (std.mem.eql(u8, decl.name, child_string)) { |
| 2040 | path[i + 1] = .{ .declRef = d }; |
| 2041 | continue :outer; |
| 2042 | } |
| 2043 | } |
| 2044 | for (t_enum.privDecls) |d| { |
| 2045 | // TODO: this could be improved a lot |
| 2046 | // by having our own string table! |
| 2047 | const decl = self.decls.items[d]; |
| 2048 | if (std.mem.eql(u8, decl.name, child_string)) { |
| 2049 | path[i + 1] = .{ .declRef = d }; |
| 2050 | continue :outer; |
| 2051 | } |
| 2052 | } |
| 2053 | |
| 2054 | for (self.ast_nodes.items[t_enum.src].fields.?) |ast_node, idx| { |
| 2055 | const name = self.ast_nodes.items[ast_node].name.?; |
| 2056 | if (std.mem.eql(u8, name, child_string)) { |
| 2057 | // TODO: should we really create an artificial |
| 2058 | // decl for this type? Probably not. |
| 2059 | |
| 2060 | path[i + 1] = .{ |
| 2061 | .fieldRef = .{ |
| 2062 | .type = t_index, |
| 2063 | .index = idx, |
| 2064 | }, |
| 2065 | }; |
| 2066 | continue :outer; |
| 2067 | } |
| 2068 | } |
| 2069 | |
| 2070 | // if we got here, our search failed |
| 2071 | printWithContext( |
| 2072 | file, |
| 2073 | inst_index, |
| 2074 | "failed to match `{s}` in enum", |
| 2075 | .{child_string}, |
| 2076 | ); |
| 2077 | |
| 2078 | path[i + 1] = try self.cteTodo("match failure"); |
| 2079 | continue :outer; |
| 2080 | }, |
| 2081 | .Union => |t_union| { |
| 2082 | for (t_union.pubDecls) |d| { |
| 2083 | // TODO: this could be improved a lot |
| 2084 | // by having our own string table! |
| 2085 | const decl = self.decls.items[d]; |
| 2086 | if (std.mem.eql(u8, decl.name, child_string)) { |
| 2087 | path[i + 1] = .{ .declRef = d }; |
| 2088 | continue :outer; |
| 2089 | } |
| 2090 | } |
| 2091 | for (t_union.privDecls) |d| { |
| 2092 | // TODO: this could be improved a lot |
| 2093 | // by having our own string table! |
| 2094 | const decl = self.decls.items[d]; |
| 2095 | if (std.mem.eql(u8, decl.name, child_string)) { |
| 2096 | path[i + 1] = .{ .declRef = d }; |
| 2097 | continue :outer; |
| 2098 | } |
| 2099 | } |
| 2100 | |
| 2101 | for (self.ast_nodes.items[t_union.src].fields.?) |ast_node, idx| { |
| 2102 | const name = self.ast_nodes.items[ast_node].name.?; |
| 2103 | if (std.mem.eql(u8, name, child_string)) { |
| 2104 | // TODO: should we really create an artificial |
| 2105 | // decl for this type? Probably not. |
| 2106 | |
| 2107 | path[i + 1] = .{ |
| 2108 | .fieldRef = .{ |
| 2109 | .type = t_index, |
| 2110 | .index = idx, |
| 2111 | }, |
| 2112 | }; |
| 2113 | continue :outer; |
| 2114 | } |
| 2115 | } |
| 2116 | |
| 2117 | // if we got here, our search failed |
| 2118 | printWithContext( |
| 2119 | file, |
| 2120 | inst_index, |
| 2121 | "failed to match `{s}` in union", |
| 2122 | .{child_string}, |
| 2123 | ); |
| 2124 | path[i + 1] = try self.cteTodo("match failure"); |
| 2125 | continue :outer; |
| 2126 | }, |
| 2127 | |
| 1974 | 2128 | .Struct => |t_struct| { |
| 1975 | | std.debug.print("search: {s}\n", .{child_string}); |
| 1976 | 2129 | for (t_struct.pubDecls) |d| { |
| 1977 | 2130 | // TODO: this could be improved a lot |
| 1978 | 2131 | // by having our own string table! |
| 1979 | 2132 | const decl = self.decls.items[d]; |
| 1980 | | std.debug.print("pub decl `{s}`\n", .{decl.name}); |
| 1981 | 2133 | if (std.mem.eql(u8, decl.name, child_string)) { |
| 1982 | | std.debug.print("match!\n", .{}); |
| 1983 | 2134 | path[i + 1] = .{ .declRef = d }; |
| 1984 | 2135 | continue :outer; |
| 1985 | 2136 | } |
| ... | ... | @@ -1988,9 +2139,7 @@ fn tryResolveRefPath( |
| 1988 | 2139 | // TODO: this could be improved a lot |
| 1989 | 2140 | // by having our own string table! |
| 1990 | 2141 | const decl = self.decls.items[d]; |
| 1991 | | std.debug.print("priv decl `{s}`\n", .{decl.name}); |
| 1992 | 2142 | if (std.mem.eql(u8, decl.name, child_string)) { |
| 1993 | | std.debug.print("match!\n", .{}); |
| 1994 | 2143 | path[i + 1] = .{ .declRef = d }; |
| 1995 | 2144 | continue :outer; |
| 1996 | 2145 | } |
| ... | ... | @@ -1998,9 +2147,7 @@ fn tryResolveRefPath( |
| 1998 | 2147 | |
| 1999 | 2148 | for (self.ast_nodes.items[t_struct.src].fields.?) |ast_node, idx| { |
| 2000 | 2149 | const name = self.ast_nodes.items[ast_node].name.?; |
| 2001 | | std.debug.print("field `{s}`\n", .{name}); |
| 2002 | 2150 | if (std.mem.eql(u8, name, child_string)) { |
| 2003 | | std.debug.print("match!\n", .{}); |
| 2004 | 2151 | // TODO: should we really create an artificial |
| 2005 | 2152 | // decl for this type? Probably not. |
| 2006 | 2153 | |
| ... | ... | @@ -2015,12 +2162,14 @@ fn tryResolveRefPath( |
| 2015 | 2162 | } |
| 2016 | 2163 | |
| 2017 | 2164 | // if we got here, our search failed |
| 2018 | | panicWithContext( |
| 2165 | printWithContext( |
| 2019 | 2166 | file, |
| 2020 | 2167 | inst_index, |
| 2021 | | "failed to match `{s}`", |
| 2168 | "failed to match `{s}` in struct", |
| 2022 | 2169 | .{child_string}, |
| 2023 | 2170 | ); |
| 2171 | path[i + 1] = try self.cteTodo("match failure"); |
| 2172 | continue :outer; |
| 2024 | 2173 | }, |
| 2025 | 2174 | }, |
| 2026 | 2175 | } |
| ... | ... | @@ -2070,7 +2219,7 @@ fn analyzeFunction( |
| 2070 | 2219 | "TODO: handle `{s}` in walkInstruction.func\n", |
| 2071 | 2220 | .{@tagName(tags[param_index])}, |
| 2072 | 2221 | ), |
| 2073 | | .param_anytype => { |
| 2222 | .param_anytype, .param_anytype_comptime => { |
| 2074 | 2223 | // TODO: where are the doc comments? |
| 2075 | 2224 | const str_tok = data[param_index].str_tok; |
| 2076 | 2225 | |
| ... | ... | @@ -2097,7 +2246,7 @@ fn analyzeFunction( |
| 2097 | 2246 | const name = file.zir.nullTerminatedString(extra.data.name); |
| 2098 | 2247 | |
| 2099 | 2248 | param_ast_indexes.appendAssumeCapacity(self.ast_nodes.items.len); |
| 2100 | | self.ast_nodes.appendAssumeCapacity(.{ |
| 2249 | try self.ast_nodes.append(self.arena, .{ |
| 2101 | 2250 | .name = name, |
| 2102 | 2251 | .docs = doc_comment, |
| 2103 | 2252 | .@"comptime" = tags[param_index] == .param_comptime, |
| ... | ... | @@ -2382,12 +2531,15 @@ fn walkRef( |
| 2382 | 2531 | /// Given a WalkResult, tries to find its type. |
| 2383 | 2532 | /// Used to analyze instructions like `array_init`, which require us to |
| 2384 | 2533 | /// inspect its first element to find out the array type. |
| 2385 | | fn typeOfWalkResult(wr: DocData.WalkResult) DocData.WalkResult { |
| 2534 | fn typeOfWalkResult(self: *Autodoc, wr: DocData.WalkResult) !DocData.WalkResult { |
| 2386 | 2535 | return switch (wr) { |
| 2387 | | else => std.debug.panic( |
| 2388 | | "TODO: handle `{s}` in typeOfWalkResult\n", |
| 2389 | | .{@tagName(wr)}, |
| 2390 | | ), |
| 2536 | else => { |
| 2537 | std.debug.print( |
| 2538 | "TODO: handle `{s}` in typeOfWalkResult\n", |
| 2539 | .{@tagName(wr)}, |
| 2540 | ); |
| 2541 | return self.cteTodo(@tagName(wr)); |
| 2542 | }, |
| 2391 | 2543 | .type => .{ .type = @enumToInt(DocData.DocTypeKinds.Type) }, |
| 2392 | 2544 | .int => |v| v.typeRef.*, |
| 2393 | 2545 | .float => |v| v.typeRef.*, |
| ... | ... | @@ -2403,9 +2555,15 @@ fn getBlockInlineBreak(zir: Zir, inst_index: usize) Zir.Inst.Ref { |
| 2403 | 2555 | return data[break_index].@"break".operand; |
| 2404 | 2556 | } |
| 2405 | 2557 | |
| 2406 | | fn panicWithContext(file: *File, inst: usize, comptime fmt: []const u8, args: anytype) noreturn { |
| 2558 | fn printWithContext(file: *File, inst: usize, comptime fmt: []const u8, args: anytype) void { |
| 2407 | 2559 | std.debug.print("Context [{s}] % {}\n", .{ file.sub_file_path, inst }); |
| 2408 | | std.debug.panic(fmt, args); |
| 2560 | std.debug.print(fmt, args); |
| 2561 | std.debug.print("\n", .{}); |
| 2562 | } |
| 2563 | |
| 2564 | fn panicWithContext(file: *File, inst: usize, comptime fmt: []const u8, args: anytype) noreturn { |
| 2565 | printWithContext(file, inst, fmt, args); |
| 2566 | unreachable; |
| 2409 | 2567 | } |
| 2410 | 2568 | |
| 2411 | 2569 | fn cteTodo(self: *Autodoc, msg: []const u8) error{OutOfMemory}!DocData.WalkResult { |