| ... | ... | @@ -60,10 +60,10 @@ pub fn generateZirData(self: *Autodoc) !void { |
| 60 | 60 | try self.types.append(self.arena, .{ |
| 61 | 61 | .name = tmpbuf.toOwnedSlice(), |
| 62 | 62 | .kind = switch (@intToEnum(Ref, i)) { |
| 63 | | else => |t| blk: { |
| 64 | | std.debug.print("TODO: categorize `{s}` in typeKinds\n", .{ |
| 65 | | @tagName(t), |
| 66 | | }); |
| 63 | else => blk: { |
| 64 | //std.debug.print("TODO: categorize `{s}` in typeKinds\n", .{ |
| 65 | // @tagName(t), |
| 66 | //}); |
| 67 | 67 | break :blk 7; |
| 68 | 68 | }, |
| 69 | 69 | .u1_type, |
| ... | ... | @@ -302,7 +302,7 @@ const DocData = struct { |
| 302 | 302 | .int => |v| { |
| 303 | 303 | const neg = if (v.negated) "-" else ""; |
| 304 | 304 | try w.print( |
| 305 | | \\{{ "int": {{ "typeRef": |
| 305 | \\{{ "int": {{ "typeRef": |
| 306 | 306 | , .{}); |
| 307 | 307 | try v.typeRef.jsonStringify(options, w); |
| 308 | 308 | try w.print( |
| ... | ... | @@ -312,7 +312,7 @@ const DocData = struct { |
| 312 | 312 | .float => |v| { |
| 313 | 313 | const neg = if (v.negated) "-" else ""; |
| 314 | 314 | try w.print( |
| 315 | | \\{{ "float": {{ "typeRef": |
| 315 | \\{{ "float": {{ "typeRef": |
| 316 | 316 | , .{}); |
| 317 | 317 | try v.typeRef.jsonStringify(options, w); |
| 318 | 318 | try w.print( |
| ... | ... | @@ -429,13 +429,6 @@ fn walkInstruction( |
| 429 | 429 | const pl_node = data[inst_index].pl_node; |
| 430 | 430 | const extra = zir.extraData(Zir.Inst.Block, pl_node.payload_index); |
| 431 | 431 | const break_index = zir.extra[extra.end..][extra.data.body_len - 1]; |
| 432 | | |
| 433 | | std.debug.print("[instr: {}] body len: {} last instr idx: {}\n", .{ |
| 434 | | inst_index, |
| 435 | | extra.data.body_len, |
| 436 | | break_index, |
| 437 | | }); |
| 438 | | |
| 439 | 432 | const break_operand = data[break_index].@"break".operand; |
| 440 | 433 | return self.walkRef(zir, parent_scope, break_operand); |
| 441 | 434 | }, |
| ... | ... | @@ -444,10 +437,227 @@ fn walkInstruction( |
| 444 | 437 | switch (extended.opcode) { |
| 445 | 438 | else => { |
| 446 | 439 | std.debug.panic( |
| 447 | | "TODO: implement `walkInstruction` (inside .extended case) for {s}\n\n", |
| 440 | "TODO: implement `walkInstruction.extended` for {s}\n\n", |
| 448 | 441 | .{@tagName(extended.opcode)}, |
| 449 | 442 | ); |
| 450 | 443 | }, |
| 444 | .union_decl => { |
| 445 | var scope: Scope = .{ .parent = parent_scope }; |
| 446 | |
| 447 | const small = @bitCast(Zir.Inst.UnionDecl.Small, extended.small); |
| 448 | var extra_index: usize = extended.operand; |
| 449 | |
| 450 | const src_node: ?i32 = if (small.has_src_node) blk: { |
| 451 | const src_node = @bitCast(i32, zir.extra[extra_index]); |
| 452 | extra_index += 1; |
| 453 | break :blk src_node; |
| 454 | } else null; |
| 455 | _ = src_node; |
| 456 | |
| 457 | const tag_type: ?Ref = if (small.has_tag_type) blk: { |
| 458 | const tag_type = zir.extra[extra_index]; |
| 459 | extra_index += 1; |
| 460 | break :blk @intToEnum(Ref, tag_type); |
| 461 | } else null; |
| 462 | _ = tag_type; |
| 463 | |
| 464 | const body_len = if (small.has_body_len) blk: { |
| 465 | const body_len = zir.extra[extra_index]; |
| 466 | extra_index += 1; |
| 467 | break :blk body_len; |
| 468 | } else 0; |
| 469 | |
| 470 | const fields_len = if (small.has_fields_len) blk: { |
| 471 | const fields_len = zir.extra[extra_index]; |
| 472 | extra_index += 1; |
| 473 | break :blk fields_len; |
| 474 | } else 0; |
| 475 | _ = fields_len; |
| 476 | |
| 477 | const decls_len = if (small.has_decls_len) blk: { |
| 478 | const decls_len = zir.extra[extra_index]; |
| 479 | extra_index += 1; |
| 480 | break :blk decls_len; |
| 481 | } else 0; |
| 482 | |
| 483 | var decl_indexes: std.ArrayListUnmanaged(usize) = .{}; |
| 484 | var priv_decl_indexes: std.ArrayListUnmanaged(usize) = .{}; |
| 485 | |
| 486 | const decls_first_index = self.decls.items.len; |
| 487 | // Decl name lookahead for reserving slots in `scope` (and `decls`). |
| 488 | // Done to make sure that all decl refs can be resolved correctly, |
| 489 | // even if we haven't fully analyzed the decl yet. |
| 490 | { |
| 491 | var it = zir.declIterator(@intCast(u32, inst_index)); |
| 492 | try self.decls.resize(self.arena, decls_first_index + it.decls_len); |
| 493 | var decls_slot_index = decls_first_index; |
| 494 | while (it.next()) |d| : (decls_slot_index += 1) { |
| 495 | const decl_name_index = zir.extra[d.sub_index + 5]; |
| 496 | try scope.insertDeclRef(self.arena, decl_name_index, decls_slot_index); |
| 497 | } |
| 498 | } |
| 499 | |
| 500 | extra_index = try self.walkDecls( |
| 501 | zir, |
| 502 | &scope, |
| 503 | decls_first_index, |
| 504 | decls_len, |
| 505 | &decl_indexes, |
| 506 | &priv_decl_indexes, |
| 507 | extra_index, |
| 508 | ); |
| 509 | |
| 510 | // const body = zir.extra[extra_index..][0..body_len]; |
| 511 | extra_index += body_len; |
| 512 | |
| 513 | var field_type_indexes: std.ArrayListUnmanaged(DocData.WalkResult) = .{}; |
| 514 | var field_name_indexes: std.ArrayListUnmanaged(usize) = .{}; |
| 515 | try self.collectUnionFieldInfo( |
| 516 | zir, |
| 517 | &scope, |
| 518 | fields_len, |
| 519 | &field_type_indexes, |
| 520 | &field_name_indexes, |
| 521 | extra_index, |
| 522 | ); |
| 523 | |
| 524 | self.ast_nodes.items[self_ast_node_index].fields = field_name_indexes.items; |
| 525 | |
| 526 | try self.types.append(self.arena, .{ |
| 527 | .kind = @enumToInt(std.builtin.TypeId.Union), |
| 528 | .name = "todo_name", |
| 529 | .src = self_ast_node_index, |
| 530 | .privDecls = priv_decl_indexes.items, |
| 531 | .pubDecls = decl_indexes.items, |
| 532 | .fields = field_type_indexes.items, |
| 533 | }); |
| 534 | |
| 535 | return DocData.WalkResult{ .type = self.types.items.len - 1 }; |
| 536 | }, |
| 537 | .enum_decl => { |
| 538 | var scope: Scope = .{ .parent = parent_scope }; |
| 539 | |
| 540 | const small = @bitCast(Zir.Inst.EnumDecl.Small, extended.small); |
| 541 | var extra_index: usize = extended.operand; |
| 542 | |
| 543 | const src_node: ?i32 = if (small.has_src_node) blk: { |
| 544 | const src_node = @bitCast(i32, zir.extra[extra_index]); |
| 545 | extra_index += 1; |
| 546 | break :blk src_node; |
| 547 | } else null; |
| 548 | _ = src_node; |
| 549 | |
| 550 | const tag_type: ?Ref = if (small.has_tag_type) blk: { |
| 551 | const tag_type = zir.extra[extra_index]; |
| 552 | extra_index += 1; |
| 553 | break :blk @intToEnum(Ref, tag_type); |
| 554 | } else null; |
| 555 | _ = tag_type; |
| 556 | |
| 557 | const body_len = if (small.has_body_len) blk: { |
| 558 | const body_len = zir.extra[extra_index]; |
| 559 | extra_index += 1; |
| 560 | break :blk body_len; |
| 561 | } else 0; |
| 562 | |
| 563 | const fields_len = if (small.has_fields_len) blk: { |
| 564 | const fields_len = zir.extra[extra_index]; |
| 565 | extra_index += 1; |
| 566 | break :blk fields_len; |
| 567 | } else 0; |
| 568 | _ = fields_len; |
| 569 | |
| 570 | const decls_len = if (small.has_decls_len) blk: { |
| 571 | const decls_len = zir.extra[extra_index]; |
| 572 | extra_index += 1; |
| 573 | break :blk decls_len; |
| 574 | } else 0; |
| 575 | |
| 576 | var decl_indexes: std.ArrayListUnmanaged(usize) = .{}; |
| 577 | var priv_decl_indexes: std.ArrayListUnmanaged(usize) = .{}; |
| 578 | |
| 579 | const decls_first_index = self.decls.items.len; |
| 580 | // Decl name lookahead for reserving slots in `scope` (and `decls`). |
| 581 | // Done to make sure that all decl refs can be resolved correctly, |
| 582 | // even if we haven't fully analyzed the decl yet. |
| 583 | { |
| 584 | var it = zir.declIterator(@intCast(u32, inst_index)); |
| 585 | try self.decls.resize(self.arena, decls_first_index + it.decls_len); |
| 586 | var decls_slot_index = decls_first_index; |
| 587 | while (it.next()) |d| : (decls_slot_index += 1) { |
| 588 | const decl_name_index = zir.extra[d.sub_index + 5]; |
| 589 | try scope.insertDeclRef(self.arena, decl_name_index, decls_slot_index); |
| 590 | } |
| 591 | } |
| 592 | |
| 593 | extra_index = try self.walkDecls( |
| 594 | zir, |
| 595 | &scope, |
| 596 | decls_first_index, |
| 597 | decls_len, |
| 598 | &decl_indexes, |
| 599 | &priv_decl_indexes, |
| 600 | extra_index, |
| 601 | ); |
| 602 | |
| 603 | // const body = zir.extra[extra_index..][0..body_len]; |
| 604 | extra_index += body_len; |
| 605 | |
| 606 | var field_name_indexes: std.ArrayListUnmanaged(usize) = .{}; |
| 607 | { |
| 608 | var bit_bag_idx = extra_index; |
| 609 | var cur_bit_bag: u32 = undefined; |
| 610 | extra_index += std.math.divCeil(usize, fields_len, 32) catch unreachable; |
| 611 | |
| 612 | var idx: usize = 0; |
| 613 | while (idx < fields_len) : (idx += 1) { |
| 614 | if (idx % 32 == 0) { |
| 615 | cur_bit_bag = zir.extra[bit_bag_idx]; |
| 616 | bit_bag_idx += 1; |
| 617 | } |
| 618 | |
| 619 | const has_value = @truncate(u1, cur_bit_bag) != 0; |
| 620 | cur_bit_bag >>= 1; |
| 621 | |
| 622 | const field_name_index = zir.extra[extra_index]; |
| 623 | extra_index += 1; |
| 624 | |
| 625 | const doc_comment_index = zir.extra[extra_index]; |
| 626 | extra_index += 1; |
| 627 | |
| 628 | const value_ref: ?Ref = if (has_value) blk: { |
| 629 | const value_ref = zir.extra[extra_index]; |
| 630 | extra_index += 1; |
| 631 | break :blk @intToEnum(Ref, value_ref); |
| 632 | } else null; |
| 633 | _ = value_ref; |
| 634 | |
| 635 | const field_name = zir.nullTerminatedString(field_name_index); |
| 636 | |
| 637 | try field_name_indexes.append(self.arena, self.ast_nodes.items.len); |
| 638 | const doc_comment: ?[]const u8 = if (doc_comment_index != 0) |
| 639 | zir.nullTerminatedString(doc_comment_index) |
| 640 | else |
| 641 | null; |
| 642 | try self.ast_nodes.append(self.arena, .{ |
| 643 | .name = field_name, |
| 644 | .docs = doc_comment, |
| 645 | }); |
| 646 | } |
| 647 | } |
| 648 | |
| 649 | self.ast_nodes.items[self_ast_node_index].fields = field_name_indexes.items; |
| 650 | |
| 651 | try self.types.append(self.arena, .{ |
| 652 | .kind = @enumToInt(std.builtin.TypeId.Enum), |
| 653 | .name = "todo_name", |
| 654 | .src = self_ast_node_index, |
| 655 | .privDecls = priv_decl_indexes.items, |
| 656 | .pubDecls = decl_indexes.items, |
| 657 | }); |
| 658 | |
| 659 | return DocData.WalkResult{ .type = self.types.items.len - 1 }; |
| 660 | }, |
| 451 | 661 | .struct_decl => { |
| 452 | 662 | var scope: Scope = .{ .parent = parent_scope }; |
| 453 | 663 | |
| ... | ... | @@ -512,7 +722,7 @@ fn walkInstruction( |
| 512 | 722 | |
| 513 | 723 | var field_type_indexes: std.ArrayListUnmanaged(DocData.WalkResult) = .{}; |
| 514 | 724 | var field_name_indexes: std.ArrayListUnmanaged(usize) = .{}; |
| 515 | | try self.collectFieldInfo( |
| 725 | try self.collectStructFieldInfo( |
| 516 | 726 | zir, |
| 517 | 727 | &scope, |
| 518 | 728 | fields_len, |
| ... | ... | @@ -539,12 +749,12 @@ fn walkInstruction( |
| 539 | 749 | } |
| 540 | 750 | } |
| 541 | 751 | |
| 542 | | /// Called by `walkInstruction` when encountering a container type, |
| 752 | /// Called by `walkInstruction` when encountering a container type, |
| 543 | 753 | /// iterates over all decl definitions in its body. |
| 544 | | /// It also analyzes each decl's body recursively. |
| 754 | /// It also analyzes each decl's body recursively. |
| 545 | 755 | /// |
| 546 | | /// Does not append to `self.decls` directly because `walkInstruction` |
| 547 | | /// is expected to (look-ahead) scan all decls and reserve `body_len` |
| 756 | /// Does not append to `self.decls` directly because `walkInstruction` |
| 757 | /// is expected to (look-ahead) scan all decls and reserve `body_len` |
| 548 | 758 | /// slots in `self.decls`, which are then filled out by `walkDecls`. |
| 549 | 759 | fn walkDecls( |
| 550 | 760 | self: *Autodoc, |
| ... | ... | @@ -678,7 +888,7 @@ fn walkDecls( |
| 678 | 888 | return extra_index; |
| 679 | 889 | } |
| 680 | 890 | |
| 681 | | fn collectFieldInfo( |
| 891 | fn collectUnionFieldInfo( |
| 682 | 892 | self: *Autodoc, |
| 683 | 893 | zir: Zir, |
| 684 | 894 | scope: *Scope, |
| ... | ... | @@ -703,9 +913,78 @@ fn collectFieldInfo( |
| 703 | 913 | cur_bit_bag = zir.extra[bit_bag_index]; |
| 704 | 914 | bit_bag_index += 1; |
| 705 | 915 | } |
| 706 | | // const has_align = @truncate(u1, cur_bit_bag) != 0; |
| 916 | const has_type = @truncate(u1, cur_bit_bag) != 0; |
| 917 | cur_bit_bag >>= 1; |
| 918 | const has_align = @truncate(u1, cur_bit_bag) != 0; |
| 919 | cur_bit_bag >>= 1; |
| 920 | const has_tag = @truncate(u1, cur_bit_bag) != 0; |
| 921 | cur_bit_bag >>= 1; |
| 922 | const unused = @truncate(u1, cur_bit_bag) != 0; |
| 707 | 923 | cur_bit_bag >>= 1; |
| 708 | | // const has_default = @truncate(u1, cur_bit_bag) != 0; |
| 924 | _ = unused; |
| 925 | |
| 926 | const field_name = zir.nullTerminatedString(zir.extra[extra_index]); |
| 927 | extra_index += 1; |
| 928 | const doc_comment_index = zir.extra[extra_index]; |
| 929 | extra_index += 1; |
| 930 | const field_type = if (has_type) |
| 931 | @intToEnum(Zir.Inst.Ref, zir.extra[extra_index]) |
| 932 | else |
| 933 | .void_type; |
| 934 | extra_index += 1; |
| 935 | |
| 936 | if (has_align) extra_index += 1; |
| 937 | if (has_tag) extra_index += 1; |
| 938 | |
| 939 | // type |
| 940 | { |
| 941 | const walk_result = try self.walkRef(zir, scope, field_type); |
| 942 | try field_type_indexes.append(self.arena, walk_result); |
| 943 | } |
| 944 | |
| 945 | // ast node |
| 946 | { |
| 947 | try field_name_indexes.append(self.arena, self.ast_nodes.items.len); |
| 948 | const doc_comment: ?[]const u8 = if (doc_comment_index != 0) |
| 949 | zir.nullTerminatedString(doc_comment_index) |
| 950 | else |
| 951 | null; |
| 952 | try self.ast_nodes.append(self.arena, .{ |
| 953 | .name = field_name, |
| 954 | .docs = doc_comment, |
| 955 | }); |
| 956 | } |
| 957 | } |
| 958 | } |
| 959 | |
| 960 | fn collectStructFieldInfo( |
| 961 | self: *Autodoc, |
| 962 | zir: Zir, |
| 963 | scope: *Scope, |
| 964 | fields_len: usize, |
| 965 | field_type_indexes: *std.ArrayListUnmanaged(DocData.WalkResult), |
| 966 | field_name_indexes: *std.ArrayListUnmanaged(usize), |
| 967 | ei: usize, |
| 968 | ) !void { |
| 969 | if (fields_len == 0) return; |
| 970 | var extra_index = ei; |
| 971 | |
| 972 | const bits_per_field = 4; |
| 973 | const fields_per_u32 = 32 / bits_per_field; |
| 974 | const bit_bags_count = std.math.divCeil(usize, fields_len, fields_per_u32) catch unreachable; |
| 975 | var bit_bag_index: usize = extra_index; |
| 976 | extra_index += bit_bags_count; |
| 977 | |
| 978 | var cur_bit_bag: u32 = undefined; |
| 979 | var field_i: u32 = 0; |
| 980 | while (field_i < fields_len) : (field_i += 1) { |
| 981 | if (field_i % fields_per_u32 == 0) { |
| 982 | cur_bit_bag = zir.extra[bit_bag_index]; |
| 983 | bit_bag_index += 1; |
| 984 | } |
| 985 | const has_align = @truncate(u1, cur_bit_bag) != 0; |
| 986 | cur_bit_bag >>= 1; |
| 987 | const has_default = @truncate(u1, cur_bit_bag) != 0; |
| 709 | 988 | cur_bit_bag >>= 1; |
| 710 | 989 | // const is_comptime = @truncate(u1, cur_bit_bag) != 0; |
| 711 | 990 | cur_bit_bag >>= 1; |
| ... | ... | @@ -720,6 +999,9 @@ fn collectFieldInfo( |
| 720 | 999 | const doc_comment_index = zir.extra[extra_index]; |
| 721 | 1000 | extra_index += 1; |
| 722 | 1001 | |
| 1002 | if (has_align) extra_index += 1; |
| 1003 | if (has_default) extra_index += 1; |
| 1004 | |
| 723 | 1005 | // type |
| 724 | 1006 | { |
| 725 | 1007 | const walk_result = try self.walkRef(zir, scope, field_type); |