| ... | @@ -411,17 +411,17 @@ const DocData = struct { | ... | @@ -411,17 +411,17 @@ const DocData = struct { |
| 411 | }, | 411 | }, |
| 412 | Enum: struct { | 412 | Enum: struct { |
| 413 | name: []const u8, | 413 | name: []const u8, |
| 414 | src: ?usize = null, // index into astNodes | 414 | src: usize, // index into astNodes |
| 415 | privDecls: ?[]usize = null, // index into decls | 415 | privDecls: []usize = &.{}, // index into decls |
| 416 | pubDecls: ?[]usize = null, // index into decls | 416 | pubDecls: []usize = &.{}, // index into decls |
| 417 | // (use src->fields to find field names) | 417 | // (use src->fields to find field names) |
| 418 | }, | 418 | }, |
| 419 | Union: struct { | 419 | Union: struct { |
| 420 | name: []const u8, | 420 | name: []const u8, |
| 421 | src: ?usize = null, // index into astNodes | 421 | src: usize, // index into astNodes |
| 422 | privDecls: ?[]usize = null, // index into decls | 422 | privDecls: []usize = &.{}, // index into decls |
| 423 | pubDecls: ?[]usize = null, // index into decls | 423 | pubDecls: []usize = &.{}, // index into decls |
| 424 | fields: ?[]WalkResult = null, // (use src->fields to find names) | 424 | fields: []WalkResult = &.{}, // (use src->fields to find names) |
| 425 | }, | 425 | }, |
| 426 | Fn: struct { | 426 | Fn: struct { |
| 427 | name: []const u8, | 427 | name: []const u8, |
| ... | @@ -465,6 +465,7 @@ const DocData = struct { | ... | @@ -465,6 +465,7 @@ const DocData = struct { |
| 465 | .Struct => |v| try printTypeBody(v, options, w), | 465 | .Struct => |v| try printTypeBody(v, options, w), |
| 466 | .Fn => |v| try printTypeBody(v, options, w), | 466 | .Fn => |v| try printTypeBody(v, options, w), |
| 467 | .Union => |v| try printTypeBody(v, options, w), | 467 | .Union => |v| try printTypeBody(v, options, w), |
| | 468 | .ErrorSet => |v| try printTypeBody(v, options, w), |
| 468 | .Enum => |v| try printTypeBody(v, options, w), | 469 | .Enum => |v| try printTypeBody(v, options, w), |
| 469 | .Int => |v| try printTypeBody(v, options, w), | 470 | .Int => |v| try printTypeBody(v, options, w), |
| 470 | .Float => |v| try printTypeBody(v, options, w), | 471 | .Float => |v| try printTypeBody(v, options, w), |
| ... | @@ -604,8 +605,12 @@ const DocData = struct { | ... | @@ -604,8 +605,12 @@ const DocData = struct { |
| 604 | , .{}); | 605 | , .{}); |
| 605 | try v.typeRef.jsonStringify(options, w); | 606 | try v.typeRef.jsonStringify(options, w); |
| 606 | try w.print( | 607 | try w.print( |
| 607 | \\, "value": {s}{} }} }} | 608 | \\, "value": {s}1 }} }} |
| 608 | , .{ neg, v.value }); | 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 | .bool => |v| { | 615 | .bool => |v| { |
| 611 | try w.print( | 616 | try w.print( |
| ... | @@ -685,12 +690,13 @@ fn walkInstruction( | ... | @@ -685,12 +690,13 @@ fn walkInstruction( |
| 685 | | 690 | |
| 686 | switch (tags[inst_index]) { | 691 | switch (tags[inst_index]) { |
| 687 | else => { | 692 | else => { |
| 688 | panicWithContext( | 693 | printWithContext( |
| 689 | file, | 694 | file, |
| 690 | inst_index, | 695 | inst_index, |
| 691 | "TODO: implement `{s}` for walkInstruction\n\n", | 696 | "TODO: implement `{s}` for walkInstruction\n\n", |
| 692 | .{@tagName(tags[inst_index])}, | 697 | .{@tagName(tags[inst_index])}, |
| 693 | ); | 698 | ); |
| | 699 | return self.cteTodo(@tagName(tags[inst_index])); |
| 694 | }, | 700 | }, |
| 695 | .closure_get => { | 701 | .closure_get => { |
| 696 | const inst_node = data[inst_index].inst_node; | 702 | const inst_node = data[inst_index].inst_node; |
| ... | @@ -752,17 +758,11 @@ fn walkInstruction( | ... | @@ -752,17 +758,11 @@ fn walkInstruction( |
| 752 | | 758 | |
| 753 | return DocData.WalkResult{ .compileError = operand.string }; | 759 | return DocData.WalkResult{ .compileError = operand.string }; |
| 754 | }, | 760 | }, |
| 755 | .switch_block => return self.cteTodo("[switch]"), | | |
| 756 | .enum_literal => { | 761 | .enum_literal => { |
| 757 | const str_tok = data[inst_index].str_tok; | 762 | const str_tok = data[inst_index].str_tok; |
| 758 | const literal = file.zir.nullTerminatedString(str_tok.start); | 763 | const literal = file.zir.nullTerminatedString(str_tok.start); |
| 759 | return DocData.WalkResult{ .enumLiteral = literal }; | 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 | .int => { | 766 | .int => { |
| 767 | const int = data[inst_index].int; | 767 | const int = data[inst_index].int; |
| 768 | const t = try self.arena.create(DocData.WalkResult); | 768 | const t = try self.arena.create(DocData.WalkResult); |
| ... | @@ -849,7 +849,7 @@ fn walkInstruction( | ... | @@ -849,7 +849,7 @@ fn walkInstruction( |
| 849 | .negated = false, | 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,7 +880,17 @@ fn walkInstruction( |
| 880 | parent_scope, | 880 | parent_scope, |
| 881 | un_node.operand, | 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 | return operand; | 894 | return operand; |
| 885 | }, | 895 | }, |
| 886 | .size_of => { | 896 | .size_of => { |
| ... | @@ -913,21 +923,19 @@ fn walkInstruction( | ... | @@ -913,21 +923,19 @@ fn walkInstruction( |
| 913 | var operand = try self.walkRef(file, parent_scope, extra.data.operand); | 923 | var operand = try self.walkRef(file, parent_scope, extra.data.operand); |
| 914 | | 924 | |
| 915 | switch (operand) { | 925 | switch (operand) { |
| 916 | else => panicWithContext( | 926 | else => printWithContext( |
| 917 | file, | 927 | file, |
| 918 | inst_index, | 928 | inst_index, |
| 919 | "TODO: handle {s} in `walkInstruction.as_node`\n", | 929 | "TODO: handle {s} in `walkInstruction.as_node`", |
| 920 | .{@tagName(operand)}, | 930 | .{@tagName(operand)}, |
| 921 | ), | 931 | ), |
| 922 | .refPath, .type, .string, .call, .enumLiteral => {}, | 932 | .declRef, .refPath, .type, .string, .call, .enumLiteral => {}, |
| 923 | // we don't do anything because up until now, | 933 | // we don't do anything because up until now, |
| 924 | // I've only seen this used as such: | 934 | // I've only seen this used as such: |
| 925 | // @as(@as(type, Baz), .{}) | 935 | // @as(@as(type, Baz), .{}) |
| 926 | // and we don't want to toss away the | 936 | // and we don't want to toss away the |
| 927 | // decl_val information (eg by replacing it with | 937 | // decl_val information (eg by replacing it with |
| 928 | // a WalkResult.type). | 938 | // a WalkResult.type). |
| 929 | // TODO: Actually, this is a good moment to check if | | |
| 930 | // the result is indeed a type!! | | |
| 931 | .comptimeExpr => { | 939 | .comptimeExpr => { |
| 932 | self.comptime_exprs.items[operand.comptimeExpr].typeRef = dest_type_ref; | 940 | self.comptime_exprs.items[operand.comptimeExpr].typeRef = dest_type_ref; |
| 933 | }, | 941 | }, |
| ... | @@ -1043,7 +1051,7 @@ fn walkInstruction( | ... | @@ -1043,7 +1051,7 @@ fn walkInstruction( |
| 1043 | var idx = extra.end; | 1051 | var idx = extra.end; |
| 1044 | for (field_vals) |*fv| { | 1052 | for (field_vals) |*fv| { |
| 1045 | const init_extra = file.zir.extraData(Zir.Inst.StructInit.Item, idx); | 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 | const field_name = blk: { | 1056 | const field_name = blk: { |
| 1049 | const field_inst_index = init_extra.data.field_type; | 1057 | const field_inst_index = init_extra.data.field_type; |
| ... | @@ -1176,53 +1184,45 @@ fn walkInstruction( | ... | @@ -1176,53 +1184,45 @@ fn walkInstruction( |
| 1176 | ); | 1184 | ); |
| 1177 | }, | 1185 | }, |
| 1178 | .extended => { | 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 | const extended = data[inst_index].extended; | 1187 | const extended = data[inst_index].extended; |
| 1207 | switch (extended.opcode) { | 1188 | switch (extended.opcode) { |
| 1208 | else => { | 1189 | else => { |
| 1209 | panicWithContext( | 1190 | printWithContext( |
| 1210 | file, | 1191 | file, |
| 1211 | inst_index, | 1192 | inst_index, |
| 1212 | "TODO: implement `walkInstruction.extended` for {s}\n\n", | 1193 | "TODO: implement `walkInstruction.extended` for {s}", |
| 1213 | .{@tagName(extended.opcode)}, | 1194 | .{@tagName(extended.opcode)}, |
| 1214 | ); | 1195 | ); |
| | 1196 | return self.cteTodo(@tagName(extended.opcode)); |
| 1215 | }, | 1197 | }, |
| 1216 | | 1198 | |
| 1217 | .opaque_decl => return self.cteTodo("opaque {...}"), | 1199 | .opaque_decl => return self.cteTodo("opaque {...}"), |
| 1218 | .func => { | 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 | file, | 1205 | file, |
| 1221 | parent_scope, | 1206 | parent_scope, |
| 1222 | inst_index, | 1207 | inst_index, |
| 1223 | self_ast_node_index, | 1208 | self_ast_node_index, |
| 1224 | type_slot_index, | 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 | .variable => { | 1227 | .variable => { |
| 1228 | const small = @bitCast(Zir.Inst.ExtendedVar.Small, extended.small); | 1228 | const small = @bitCast(Zir.Inst.ExtendedVar.Small, extended.small); |
| ... | @@ -1237,6 +1237,9 @@ fn walkInstruction( | ... | @@ -1237,6 +1237,9 @@ fn walkInstruction( |
| 1237 | return value; | 1237 | return value; |
| 1238 | }, | 1238 | }, |
| 1239 | .union_decl => { | 1239 | .union_decl => { |
| | 1240 | const type_slot_index = self.types.items.len; |
| | 1241 | try self.types.append(self.arena, .{ .Unanalyzed = {} }); |
| | 1242 | |
| 1240 | var scope: Scope = .{ | 1243 | var scope: Scope = .{ |
| 1241 | .parent = parent_scope, | 1244 | .parent = parent_scope, |
| 1242 | .enclosing_type = type_slot_index, | 1245 | .enclosing_type = type_slot_index, |
| ... | @@ -1340,9 +1343,27 @@ fn walkInstruction( | ... | @@ -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 | return DocData.WalkResult{ .type = type_slot_index }; | 1361 | return DocData.WalkResult{ .type = type_slot_index }; |
| 1344 | }, | 1362 | }, |
| 1345 | .enum_decl => { | 1363 | .enum_decl => { |
| | 1364 | const type_slot_index = self.types.items.len; |
| | 1365 | try self.types.append(self.arena, .{ .Unanalyzed = {} }); |
| | 1366 | |
| 1346 | var scope: Scope = .{ | 1367 | var scope: Scope = .{ |
| 1347 | .parent = parent_scope, | 1368 | .parent = parent_scope, |
| 1348 | .enclosing_type = type_slot_index, | 1369 | .enclosing_type = type_slot_index, |
| ... | @@ -1470,10 +1491,27 @@ fn walkInstruction( | ... | @@ -1470,10 +1491,27 @@ fn walkInstruction( |
| 1470 | .pubDecls = decl_indexes.items, | 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 | return DocData.WalkResult{ .type = type_slot_index }; | 1509 | return DocData.WalkResult{ .type = type_slot_index }; |
| 1475 | }, | 1510 | }, |
| 1476 | .struct_decl => { | 1511 | .struct_decl => { |
| | 1512 | const type_slot_index = self.types.items.len; |
| | 1513 | try self.types.append(self.arena, .{ .Unanalyzed = {} }); |
| | 1514 | |
| 1477 | var scope: Scope = .{ | 1515 | var scope: Scope = .{ |
| 1478 | .parent = parent_scope, | 1516 | .parent = parent_scope, |
| 1479 | .enclosing_type = type_slot_index, | 1517 | .enclosing_type = type_slot_index, |
| ... | @@ -1563,6 +1601,20 @@ fn walkInstruction( | ... | @@ -1563,6 +1601,20 @@ fn walkInstruction( |
| 1563 | .fields = field_type_refs.items, | 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 | return DocData.WalkResult{ .type = type_slot_index }; | 1619 | return DocData.WalkResult{ .type = type_slot_index }; |
| 1568 | }, | 1620 | }, |
| ... | @@ -1608,9 +1660,9 @@ fn walkDecls( | ... | @@ -1608,9 +1660,9 @@ fn walkDecls( |
| 1608 | cur_bit_bag >>= 1; | 1660 | cur_bit_bag >>= 1; |
| 1609 | const is_exported = @truncate(u1, cur_bit_bag) != 0; | 1661 | const is_exported = @truncate(u1, cur_bit_bag) != 0; |
| 1610 | cur_bit_bag >>= 1; | 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 | cur_bit_bag >>= 1; | 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 | cur_bit_bag >>= 1; | 1666 | cur_bit_bag >>= 1; |
| 1615 | | 1667 | |
| 1616 | // const sub_index = extra_index; | 1668 | // const sub_index = extra_index; |
| ... | @@ -1626,21 +1678,26 @@ fn walkDecls( | ... | @@ -1626,21 +1678,26 @@ fn walkDecls( |
| 1626 | const doc_comment_index = file.zir.extra[extra_index]; | 1678 | const doc_comment_index = file.zir.extra[extra_index]; |
| 1627 | extra_index += 1; | 1679 | extra_index += 1; |
| 1628 | | 1680 | |
| 1629 | // const align_inst: Zir.Inst.Ref = if (!has_align) .none else inst: { | 1681 | const align_inst: Zir.Inst.Ref = if (!has_align) .none else inst: { |
| 1630 | // const inst = @intToEnum(Zir.Inst.Ref, file.zir.extra[extra_index]); | 1682 | const inst = @intToEnum(Zir.Inst.Ref, file.zir.extra[extra_index]); |
| 1631 | // extra_index += 1; | 1683 | extra_index += 1; |
| 1632 | // break :inst inst; | 1684 | break :inst inst; |
| 1633 | // }; | 1685 | }; |
| 1634 | // const section_inst: Zir.Inst.Ref = if (!has_section_or_addrspace) .none else inst: { | 1686 | _ = align_inst; |
| 1635 | // const inst = @intToEnum(Zir.Inst.Ref, file.zir.extra[extra_index]); | 1687 | |
| 1636 | // extra_index += 1; | 1688 | const section_inst: Zir.Inst.Ref = if (!has_section_or_addrspace) .none else inst: { |
| 1637 | // break :inst inst; | 1689 | const inst = @intToEnum(Zir.Inst.Ref, file.zir.extra[extra_index]); |
| 1638 | // }; | 1690 | extra_index += 1; |
| 1639 | // const addrspace_inst: Zir.Inst.Ref = if (!has_section_or_addrspace) .none else inst: { | 1691 | break :inst inst; |
| 1640 | // const inst = @intToEnum(Zir.Inst.Ref, file.zir.extra[extra_index]); | 1692 | }; |
| 1641 | // extra_index += 1; | 1693 | _ = section_inst; |
| 1642 | // break :inst inst; | 1694 | |
| 1643 | // }; | 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 | // const pub_str = if (is_pub) "pub " else ""; | 1702 | // const pub_str = if (is_pub) "pub " else ""; |
| 1646 | // const hash_bytes = @bitCast([16]u8, hash_u32s.*); | 1703 | // const hash_bytes = @bitCast([16]u8, hash_u32s.*); |
| ... | @@ -1848,6 +1905,7 @@ fn tryResolveRefPath( | ... | @@ -1848,6 +1905,7 @@ fn tryResolveRefPath( |
| 1848 | while (j < 10_000) : (j += 1) { | 1905 | while (j < 10_000) : (j += 1) { |
| 1849 | switch (resolved_parent) { | 1906 | switch (resolved_parent) { |
| 1850 | else => break, | 1907 | else => break, |
| | 1908 | .this => |t| resolved_parent = .{ .type = t }, |
| 1851 | .declRef => |decl_index| { | 1909 | .declRef => |decl_index| { |
| 1852 | const decl = self.decls.items[decl_index]; | 1910 | const decl = self.decls.items[decl_index]; |
| 1853 | if (decl._analyzed) { | 1911 | if (decl._analyzed) { |
| ... | @@ -1927,12 +1985,14 @@ fn tryResolveRefPath( | ... | @@ -1927,12 +1985,14 @@ fn tryResolveRefPath( |
| 1927 | else => { | 1985 | else => { |
| 1928 | // NOTE: indirect references to types / decls should be handled | 1986 | // NOTE: indirect references to types / decls should be handled |
| 1929 | // in the switch above this one! | 1987 | // in the switch above this one! |
| 1930 | panicWithContext( | 1988 | printWithContext( |
| 1931 | file, | 1989 | file, |
| 1932 | inst_index, | 1990 | inst_index, |
| 1933 | "TODO: handle `{s}`in tryResolveRefPath\nInfo: {}", | 1991 | "TODO: handle `{s}`in tryResolveRefPath\nInfo: {}", |
| 1934 | .{ @tagName(resolved_parent), resolved_parent }, | 1992 | .{ @tagName(resolved_parent), resolved_parent }, |
| 1935 | ); | 1993 | ); |
| | 1994 | path[i + 1] = try self.cteTodo("match failure"); |
| | 1995 | continue :outer; |
| 1936 | }, | 1996 | }, |
| 1937 | .comptimeExpr, .call => { | 1997 | .comptimeExpr, .call => { |
| 1938 | // Since we hit a cte, we leave the remaining strings unresolved | 1998 | // Since we hit a cte, we leave the remaining strings unresolved |
| ... | @@ -1971,15 +2031,106 @@ fn tryResolveRefPath( | ... | @@ -1971,15 +2031,106 @@ fn tryResolveRefPath( |
| 1971 | | 2031 | |
| 1972 | return; | 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 | .Struct => |t_struct| { | 2128 | .Struct => |t_struct| { |
| 1975 | std.debug.print("search: {s}\n", .{child_string}); | | |
| 1976 | for (t_struct.pubDecls) |d| { | 2129 | for (t_struct.pubDecls) |d| { |
| 1977 | // TODO: this could be improved a lot | 2130 | // TODO: this could be improved a lot |
| 1978 | // by having our own string table! | 2131 | // by having our own string table! |
| 1979 | const decl = self.decls.items[d]; | 2132 | const decl = self.decls.items[d]; |
| 1980 | std.debug.print("pub decl `{s}`\n", .{decl.name}); | | |
| 1981 | if (std.mem.eql(u8, decl.name, child_string)) { | 2133 | if (std.mem.eql(u8, decl.name, child_string)) { |
| 1982 | std.debug.print("match!\n", .{}); | | |
| 1983 | path[i + 1] = .{ .declRef = d }; | 2134 | path[i + 1] = .{ .declRef = d }; |
| 1984 | continue :outer; | 2135 | continue :outer; |
| 1985 | } | 2136 | } |
| ... | @@ -1988,9 +2139,7 @@ fn tryResolveRefPath( | ... | @@ -1988,9 +2139,7 @@ fn tryResolveRefPath( |
| 1988 | // TODO: this could be improved a lot | 2139 | // TODO: this could be improved a lot |
| 1989 | // by having our own string table! | 2140 | // by having our own string table! |
| 1990 | const decl = self.decls.items[d]; | 2141 | const decl = self.decls.items[d]; |
| 1991 | std.debug.print("priv decl `{s}`\n", .{decl.name}); | | |
| 1992 | if (std.mem.eql(u8, decl.name, child_string)) { | 2142 | if (std.mem.eql(u8, decl.name, child_string)) { |
| 1993 | std.debug.print("match!\n", .{}); | | |
| 1994 | path[i + 1] = .{ .declRef = d }; | 2143 | path[i + 1] = .{ .declRef = d }; |
| 1995 | continue :outer; | 2144 | continue :outer; |
| 1996 | } | 2145 | } |
| ... | @@ -1998,9 +2147,7 @@ fn tryResolveRefPath( | ... | @@ -1998,9 +2147,7 @@ fn tryResolveRefPath( |
| 1998 | | 2147 | |
| 1999 | for (self.ast_nodes.items[t_struct.src].fields.?) |ast_node, idx| { | 2148 | for (self.ast_nodes.items[t_struct.src].fields.?) |ast_node, idx| { |
| 2000 | const name = self.ast_nodes.items[ast_node].name.?; | 2149 | const name = self.ast_nodes.items[ast_node].name.?; |
| 2001 | std.debug.print("field `{s}`\n", .{name}); | | |
| 2002 | if (std.mem.eql(u8, name, child_string)) { | 2150 | if (std.mem.eql(u8, name, child_string)) { |
| 2003 | std.debug.print("match!\n", .{}); | | |
| 2004 | // TODO: should we really create an artificial | 2151 | // TODO: should we really create an artificial |
| 2005 | // decl for this type? Probably not. | 2152 | // decl for this type? Probably not. |
| 2006 | | 2153 | |
| ... | @@ -2015,12 +2162,14 @@ fn tryResolveRefPath( | ... | @@ -2015,12 +2162,14 @@ fn tryResolveRefPath( |
| 2015 | } | 2162 | } |
| 2016 | | 2163 | |
| 2017 | // if we got here, our search failed | 2164 | // if we got here, our search failed |
| 2018 | panicWithContext( | 2165 | printWithContext( |
| 2019 | file, | 2166 | file, |
| 2020 | inst_index, | 2167 | inst_index, |
| 2021 | "failed to match `{s}`", | 2168 | "failed to match `{s}` in struct", |
| 2022 | .{child_string}, | 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,7 +2219,7 @@ fn analyzeFunction( |
| 2070 | "TODO: handle `{s}` in walkInstruction.func\n", | 2219 | "TODO: handle `{s}` in walkInstruction.func\n", |
| 2071 | .{@tagName(tags[param_index])}, | 2220 | .{@tagName(tags[param_index])}, |
| 2072 | ), | 2221 | ), |
| 2073 | .param_anytype => { | 2222 | .param_anytype, .param_anytype_comptime => { |
| 2074 | // TODO: where are the doc comments? | 2223 | // TODO: where are the doc comments? |
| 2075 | const str_tok = data[param_index].str_tok; | 2224 | const str_tok = data[param_index].str_tok; |
| 2076 | | 2225 | |
| ... | @@ -2097,7 +2246,7 @@ fn analyzeFunction( | ... | @@ -2097,7 +2246,7 @@ fn analyzeFunction( |
| 2097 | const name = file.zir.nullTerminatedString(extra.data.name); | 2246 | const name = file.zir.nullTerminatedString(extra.data.name); |
| 2098 | | 2247 | |
| 2099 | param_ast_indexes.appendAssumeCapacity(self.ast_nodes.items.len); | 2248 | param_ast_indexes.appendAssumeCapacity(self.ast_nodes.items.len); |
| 2100 | self.ast_nodes.appendAssumeCapacity(.{ | 2249 | try self.ast_nodes.append(self.arena, .{ |
| 2101 | .name = name, | 2250 | .name = name, |
| 2102 | .docs = doc_comment, | 2251 | .docs = doc_comment, |
| 2103 | .@"comptime" = tags[param_index] == .param_comptime, | 2252 | .@"comptime" = tags[param_index] == .param_comptime, |
| ... | @@ -2382,12 +2531,15 @@ fn walkRef( | ... | @@ -2382,12 +2531,15 @@ fn walkRef( |
| 2382 | /// Given a WalkResult, tries to find its type. | 2531 | /// Given a WalkResult, tries to find its type. |
| 2383 | /// Used to analyze instructions like `array_init`, which require us to | 2532 | /// Used to analyze instructions like `array_init`, which require us to |
| 2384 | /// inspect its first element to find out the array type. | 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 | return switch (wr) { | 2535 | return switch (wr) { |
| 2387 | else => std.debug.panic( | 2536 | else => { |
| 2388 | "TODO: handle `{s}` in typeOfWalkResult\n", | 2537 | std.debug.print( |
| 2389 | .{@tagName(wr)}, | 2538 | "TODO: handle `{s}` in typeOfWalkResult\n", |
| 2390 | ), | 2539 | .{@tagName(wr)}, |
| | 2540 | ); |
| | 2541 | return self.cteTodo(@tagName(wr)); |
| | 2542 | }, |
| 2391 | .type => .{ .type = @enumToInt(DocData.DocTypeKinds.Type) }, | 2543 | .type => .{ .type = @enumToInt(DocData.DocTypeKinds.Type) }, |
| 2392 | .int => |v| v.typeRef.*, | 2544 | .int => |v| v.typeRef.*, |
| 2393 | .float => |v| v.typeRef.*, | 2545 | .float => |v| v.typeRef.*, |
| ... | @@ -2403,9 +2555,15 @@ fn getBlockInlineBreak(zir: Zir, inst_index: usize) Zir.Inst.Ref { | ... | @@ -2403,9 +2555,15 @@ fn getBlockInlineBreak(zir: Zir, inst_index: usize) Zir.Inst.Ref { |
| 2403 | return data[break_index].@"break".operand; | 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 | std.debug.print("Context [{s}] % {}\n", .{ file.sub_file_path, inst }); | 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 | fn cteTodo(self: *Autodoc, msg: []const u8) error{OutOfMemory}!DocData.WalkResult { | 2569 | fn cteTodo(self: *Autodoc, msg: []const u8) error{OutOfMemory}!DocData.WalkResult { |