| ... | ... | @@ -17,13 +17,14 @@ files: std.AutoHashMapUnmanaged(*File, usize) = .{}, |
| 17 | 17 | calls: std.ArrayListUnmanaged(DocData.Call) = .{}, |
| 18 | 18 | types: std.ArrayListUnmanaged(DocData.Type) = .{}, |
| 19 | 19 | decls: std.ArrayListUnmanaged(DocData.Decl) = .{}, |
| 20 | exprs: std.ArrayListUnmanaged(DocData.Expr) = .{}, |
| 20 | 21 | ast_nodes: std.ArrayListUnmanaged(DocData.AstNode) = .{}, |
| 21 | 22 | comptime_exprs: std.ArrayListUnmanaged(DocData.ComptimeExpr) = .{}, |
| 22 | 23 | |
| 23 | 24 | // These fields hold temporary state of the analysis process |
| 24 | 25 | // and are mainly used by the decl path resolving algorithm. |
| 25 | 26 | pending_ref_paths: std.AutoHashMapUnmanaged( |
| 26 | | *DocData.WalkResult, // pointer to declpath tail end (ie `&decl_path[decl_path.len - 1]`) |
| 27 | *DocData.Expr, // pointer to declpath tail end (ie `&decl_path[decl_path.len - 1]`) |
| 27 | 28 | std.ArrayListUnmanaged(RefPathResumeInfo), |
| 28 | 29 | ) = .{}, |
| 29 | 30 | ref_paths_pending_on_decls: std.AutoHashMapUnmanaged( |
| ... | ... | @@ -37,7 +38,7 @@ ref_paths_pending_on_types: std.AutoHashMapUnmanaged( |
| 37 | 38 | |
| 38 | 39 | const RefPathResumeInfo = struct { |
| 39 | 40 | file: *File, |
| 40 | | ref_path: []DocData.WalkResult, |
| 41 | ref_path: []DocData.Expr, |
| 41 | 42 | }; |
| 42 | 43 | |
| 43 | 44 | var arena_allocator: std.heap.ArenaAllocator = undefined; |
| ... | ... | @@ -80,7 +81,6 @@ pub fn generateZirData(self: *Autodoc) !void { |
| 80 | 81 | .ComptimeExpr = .{ .name = "ComptimeExpr" }, |
| 81 | 82 | }); |
| 82 | 83 | |
| 83 | | var tr = DocData.WalkResult{ .type = @enumToInt(Ref.usize_type) }; |
| 84 | 84 | // this skipts Ref.none but it's ok becuse we replaced it with ComptimeExpr |
| 85 | 85 | var i: u32 = 1; |
| 86 | 86 | while (i <= @enumToInt(Ref.anyerror_void_error_union_type)) : (i += 1) { |
| ... | ... | @@ -96,7 +96,6 @@ pub fn generateZirData(self: *Autodoc) !void { |
| 96 | 96 | .Array = .{ |
| 97 | 97 | .len = .{ |
| 98 | 98 | .int = .{ |
| 99 | | .typeRef = &tr, |
| 100 | 99 | .value = 1, |
| 101 | 100 | .negated = false, |
| 102 | 101 | }, |
| ... | ... | @@ -163,7 +162,7 @@ pub fn generateZirData(self: *Autodoc) !void { |
| 163 | 162 | var root_scope = Scope{ .parent = null, .enclosing_type = main_type_index }; |
| 164 | 163 | try self.ast_nodes.append(self.arena, .{ .name = "(root)" }); |
| 165 | 164 | try self.files.put(self.arena, file, main_type_index); |
| 166 | | _ = try self.walkInstruction(file, &root_scope, Zir.main_struct_inst); |
| 165 | _ = try self.walkInstruction(file, &root_scope, Zir.main_struct_inst, false); |
| 167 | 166 | |
| 168 | 167 | if (self.ref_paths_pending_on_decls.count() > 0) { |
| 169 | 168 | @panic("some decl paths were never fully analized (pending on decls)"); |
| ... | ... | @@ -182,6 +181,7 @@ pub fn generateZirData(self: *Autodoc) !void { |
| 182 | 181 | .calls = self.calls.items, |
| 183 | 182 | .types = self.types.items, |
| 184 | 183 | .decls = self.decls.items, |
| 184 | .exprs = self.exprs.items, |
| 185 | 185 | .astNodes = self.ast_nodes.items, |
| 186 | 186 | .comptimeExprs = self.comptime_exprs.items, |
| 187 | 187 | }; |
| ... | ... | @@ -305,11 +305,12 @@ const DocData = struct { |
| 305 | 305 | }, |
| 306 | 306 | types: []Type, |
| 307 | 307 | decls: []Decl, |
| 308 | exprs: []Expr, |
| 308 | 309 | comptimeExprs: []ComptimeExpr, |
| 309 | 310 | const Call = struct { |
| 310 | | func: WalkResult, |
| 311 | | args: []WalkResult, |
| 312 | | ret: WalkResult, |
| 311 | func: Expr, |
| 312 | args: []Expr, |
| 313 | ret: Expr, |
| 313 | 314 | }; |
| 314 | 315 | |
| 315 | 316 | /// All the type "families" as described by `std.builtin.TypeId` |
| ... | ... | @@ -340,7 +341,6 @@ const DocData = struct { |
| 340 | 341 | |
| 341 | 342 | const ComptimeExpr = struct { |
| 342 | 343 | code: []const u8, |
| 343 | | typeRef: WalkResult, |
| 344 | 344 | }; |
| 345 | 345 | const Package = struct { |
| 346 | 346 | name: []const u8 = "root", |
| ... | ... | @@ -356,7 +356,6 @@ const DocData = struct { |
| 356 | 356 | kind: []const u8, |
| 357 | 357 | isTest: bool, |
| 358 | 358 | src: usize, // index into astNodes |
| 359 | | // typeRef: TypeRef, |
| 360 | 359 | value: WalkResult, |
| 361 | 360 | // The index in astNodes of the `test declname { }` node |
| 362 | 361 | decltest: ?usize = null, |
| ... | ... | @@ -383,18 +382,18 @@ const DocData = struct { |
| 383 | 382 | Float: struct { name: []const u8 }, |
| 384 | 383 | Pointer: struct { |
| 385 | 384 | size: std.builtin.TypeInfo.Pointer.Size, |
| 386 | | child: WalkResult, |
| 385 | child: Expr, |
| 387 | 386 | }, |
| 388 | 387 | Array: struct { |
| 389 | | len: WalkResult, |
| 390 | | child: WalkResult, |
| 388 | len: Expr, |
| 389 | child: Expr, |
| 391 | 390 | }, |
| 392 | 391 | Struct: struct { |
| 393 | 392 | name: []const u8, |
| 394 | 393 | src: usize, // index into astNodes |
| 395 | 394 | privDecls: []usize = &.{}, // index into decls |
| 396 | 395 | pubDecls: []usize = &.{}, // index into decls |
| 397 | | fields: ?[]WalkResult = null, // (use src->fields to find names) |
| 396 | fields: ?[]Expr = null, // (use src->fields to find names) |
| 398 | 397 | }, |
| 399 | 398 | ComptimeExpr: struct { name: []const u8 }, |
| 400 | 399 | ComptimeFloat: struct { name: []const u8 }, |
| ... | ... | @@ -403,7 +402,7 @@ const DocData = struct { |
| 403 | 402 | Null: struct { name: []const u8 }, |
| 404 | 403 | Optional: struct { |
| 405 | 404 | name: []const u8, |
| 406 | | child: WalkResult, |
| 405 | child: Expr, |
| 407 | 406 | }, |
| 408 | 407 | ErrorUnion: struct { name: []const u8 }, |
| 409 | 408 | ErrorSet: struct { |
| ... | ... | @@ -423,13 +422,13 @@ const DocData = struct { |
| 423 | 422 | src: usize, // index into astNodes |
| 424 | 423 | privDecls: []usize = &.{}, // index into decls |
| 425 | 424 | pubDecls: []usize = &.{}, // index into decls |
| 426 | | fields: []WalkResult = &.{}, // (use src->fields to find names) |
| 425 | fields: []Expr = &.{}, // (use src->fields to find names) |
| 427 | 426 | }, |
| 428 | 427 | Fn: struct { |
| 429 | 428 | name: []const u8, |
| 430 | 429 | src: ?usize = null, // index into astNodes |
| 431 | | ret: WalkResult, |
| 432 | | params: ?[]WalkResult = null, // (use src->fields to find names) |
| 430 | ret: Expr, |
| 431 | params: ?[]Expr = null, // (use src->fields to find names) |
| 433 | 432 | }, |
| 434 | 433 | BoundFn: struct { name: []const u8 }, |
| 435 | 434 | Opaque: struct { name: []const u8 }, |
| ... | ... | @@ -517,75 +516,61 @@ const DocData = struct { |
| 517 | 516 | } |
| 518 | 517 | }; |
| 519 | 518 | |
| 520 | | /// A WalkResult represents the result of the analysis process done to a |
| 521 | | /// declaration. This includes: decls, fields, etc. |
| 522 | | /// |
| 523 | | /// The data in WalkResult is mostly normalized, which means that a |
| 524 | | /// WalkResult that results in a type definition will hold an index into |
| 525 | | /// `self.types`. |
| 526 | | const WalkResult = union(enum) { |
| 519 | /// An Expr represents the (untyped) result of analizing instructions. |
| 520 | /// The data is normalized, which means that an Expr that results in a |
| 521 | /// type definition will hold an index into `self.types`. |
| 522 | pub const Expr = union(enum) { |
| 527 | 523 | comptimeExpr: usize, // index in `comptimeExprs` |
| 528 | 524 | void, |
| 529 | 525 | @"unreachable", |
| 530 | | @"null": *WalkResult, |
| 531 | | @"undefined": *WalkResult, |
| 532 | | @"struct": Struct, |
| 526 | @"null", |
| 527 | @"undefined", |
| 528 | @"struct": []FieldVal, |
| 533 | 529 | bool: bool, |
| 534 | 530 | @"anytype", |
| 535 | 531 | type: usize, // index in `types` |
| 536 | 532 | this: usize, // index in `types` |
| 537 | 533 | declRef: usize, // index in `decls` |
| 538 | 534 | fieldRef: FieldRef, |
| 539 | | refPath: []WalkResult, |
| 535 | refPath: []Expr, |
| 540 | 536 | int: struct { |
| 541 | | typeRef: *WalkResult, |
| 542 | 537 | value: usize, // direct value |
| 543 | 538 | negated: bool = false, |
| 544 | 539 | }, |
| 545 | | float: struct { |
| 546 | | typeRef: *WalkResult, |
| 547 | | value: f64, // direct value |
| 548 | | negated: bool = false, |
| 549 | | }, |
| 550 | | array: Array, |
| 540 | float: f64, // direct value |
| 541 | array: []usize, // index in `exprs` |
| 551 | 542 | call: usize, // index in `calls` |
| 552 | | enumLiteral: []const u8, |
| 553 | | typeOf: *WalkResult, |
| 554 | | sizeOf: *WalkResult, |
| 543 | enumLiteral: []const u8, // direct value |
| 544 | typeOf: usize, // index in `exprs` |
| 545 | as: struct { |
| 546 | typeRefArg: ?usize, // index in `exprs` |
| 547 | exprArg: usize, // index in `exprs` |
| 548 | }, |
| 549 | sizeOf: usize, // index in `exprs` |
| 555 | 550 | compileError: []const u8, |
| 556 | | string: []const u8, |
| 557 | | |
| 551 | string: []const u8, // direct value |
| 558 | 552 | const FieldRef = struct { |
| 559 | 553 | type: usize, // index in `types` |
| 560 | 554 | index: usize, // index in type.fields |
| 561 | 555 | }; |
| 562 | 556 | |
| 563 | | const Struct = struct { |
| 564 | | typeRef: *WalkResult, |
| 565 | | fieldVals: []FieldVal, |
| 566 | | |
| 567 | | const FieldVal = struct { |
| 568 | | name: []const u8, |
| 569 | | val: WalkResult, |
| 570 | | }; |
| 571 | | }; |
| 572 | | const Array = struct { |
| 573 | | typeRef: *WalkResult, |
| 574 | | data: []WalkResult, |
| 557 | const FieldVal = struct { |
| 558 | name: []const u8, |
| 559 | val: WalkResult, |
| 575 | 560 | }; |
| 576 | 561 | |
| 577 | 562 | pub fn jsonStringify( |
| 578 | | self: WalkResult, |
| 563 | self: Expr, |
| 579 | 564 | options: std.json.StringifyOptions, |
| 580 | 565 | w: anytype, |
| 581 | 566 | ) std.os.WriteError!void { |
| 582 | 567 | switch (self) { |
| 583 | | .void, .@"unreachable", .@"anytype" => { |
| 568 | .void, .@"unreachable", .@"anytype", .@"null", .@"undefined" => { |
| 584 | 569 | try w.print( |
| 585 | 570 | \\{{ "{s}":{{}} }} |
| 586 | 571 | , .{@tagName(self)}); |
| 587 | 572 | }, |
| 588 | | .type, .comptimeExpr, .call, .this, .declRef => |v| { |
| 573 | .type, .comptimeExpr, .call, .this, .declRef, .typeOf => |v| { |
| 589 | 574 | try w.print( |
| 590 | 575 | \\{{ "{s}":{} }} |
| 591 | 576 | , .{ @tagName(self), v }); |
| ... | ... | @@ -593,43 +578,28 @@ const DocData = struct { |
| 593 | 578 | .int => |v| { |
| 594 | 579 | const neg = if (v.negated) "-" else ""; |
| 595 | 580 | try w.print( |
| 596 | | \\{{ "int": {{ "typeRef": |
| 597 | | , .{}); |
| 598 | | try v.typeRef.jsonStringify(options, w); |
| 599 | | try w.print( |
| 600 | | \\, "value": {s}{} }} }} |
| 581 | \\{{ "int": {s}{} }} |
| 601 | 582 | , .{ neg, v.value }); |
| 602 | 583 | }, |
| 603 | 584 | .float => |v| { |
| 604 | | const neg = if (v.negated) "-" else ""; |
| 605 | | try w.print( |
| 606 | | \\{{ "float": {{ "typeRef": |
| 607 | | , .{}); |
| 608 | | try v.typeRef.jsonStringify(options, w); |
| 609 | 585 | try w.print( |
| 610 | | \\, "value": {s}1 }} }} |
| 611 | | , .{neg}); |
| 612 | | // TODO: uncomment once float panic is fixed in stdlib |
| 613 | | // See: https://github.com/ziglang/zig/issues/11283 |
| 614 | | // try w.print( |
| 615 | | // \\, "value": {s}{e} }} }} |
| 616 | | // , .{ neg, v.value }); |
| 586 | \\{{ "float": {} }} |
| 587 | , .{v}); |
| 617 | 588 | }, |
| 618 | 589 | .bool => |v| { |
| 619 | 590 | try w.print( |
| 620 | 591 | \\{{ "bool":{} }} |
| 621 | 592 | , .{v}); |
| 622 | 593 | }, |
| 623 | | .@"undefined" => |v| try std.json.stringify(v, options, w), |
| 624 | | .@"null" => |v| try std.json.stringify(v, options, w), |
| 625 | | .typeOf, .sizeOf => |v| try std.json.stringify(v, options, w), |
| 594 | .sizeOf => |v| try std.json.stringify(v, options, w), |
| 595 | .as => |v| try std.json.stringify(v, options, w), |
| 626 | 596 | .fieldRef => |v| try std.json.stringify( |
| 627 | 597 | struct { fieldRef: FieldRef }{ .fieldRef = v }, |
| 628 | 598 | options, |
| 629 | 599 | w, |
| 630 | 600 | ), |
| 631 | 601 | .@"struct" => |v| try std.json.stringify( |
| 632 | | struct { @"struct": Struct }{ .@"struct" = v }, |
| 602 | struct { @"struct": []FieldVal }{ .@"struct" = v }, |
| 633 | 603 | options, |
| 634 | 604 | w, |
| 635 | 605 | ), |
| ... | ... | @@ -642,7 +612,7 @@ const DocData = struct { |
| 642 | 612 | } |
| 643 | 613 | }, |
| 644 | 614 | .array => |v| try std.json.stringify( |
| 645 | | struct { @"array": Array }{ .@"array" = v }, |
| 615 | struct { @"array": []usize }{ .@"array" = v }, |
| 646 | 616 | options, |
| 647 | 617 | w, |
| 648 | 618 | ), |
| ... | ... | @@ -677,6 +647,17 @@ const DocData = struct { |
| 677 | 647 | } |
| 678 | 648 | } |
| 679 | 649 | }; |
| 650 | |
| 651 | /// A WalkResult represents the result of the analysis process done to a |
| 652 | /// a Zir instruction. Walk results carry type information either inferred |
| 653 | /// from the context (eg string literals are pointers to null-terminated |
| 654 | /// arrays), or because of @as() instructions. |
| 655 | /// Since the type information is only needed in certain contexts, the |
| 656 | /// underlying normalized data (Expr) is untyped. |
| 657 | const WalkResult = struct { |
| 658 | typeRef: ?Expr = null, // index in `exprs` |
| 659 | expr: Expr, // index in `exprs` |
| 660 | }; |
| 680 | 661 | }; |
| 681 | 662 | |
| 682 | 663 | /// Called when we need to analyze a Zir instruction. |
| ... | ... | @@ -692,6 +673,7 @@ fn walkInstruction( |
| 692 | 673 | file: *File, |
| 693 | 674 | parent_scope: *Scope, |
| 694 | 675 | inst_index: usize, |
| 676 | need_type: bool, // true if the caller needs us to provide also a typeRef |
| 695 | 677 | ) error{OutOfMemory}!DocData.WalkResult { |
| 696 | 678 | const tags = file.zir.instructions.items(.tag); |
| 697 | 679 | const data = file.zir.instructions.items(.data); |
| ... | ... | @@ -711,11 +693,11 @@ fn walkInstruction( |
| 711 | 693 | }, |
| 712 | 694 | .closure_get => { |
| 713 | 695 | const inst_node = data[inst_index].inst_node; |
| 714 | | return try self.walkInstruction(file, parent_scope, inst_node.inst); |
| 696 | return try self.walkInstruction(file, parent_scope, inst_node.inst, need_type); |
| 715 | 697 | }, |
| 716 | 698 | .closure_capture => { |
| 717 | 699 | const un_tok = data[inst_index].un_tok; |
| 718 | | return try self.walkRef(file, parent_scope, un_tok.operand); |
| 700 | return try self.walkRef(file, parent_scope, un_tok.operand, need_type); |
| 719 | 701 | }, |
| 720 | 702 | .import => { |
| 721 | 703 | const str_tok = data[inst_index].str_tok; |
| ... | ... | @@ -726,17 +708,20 @@ fn walkInstruction( |
| 726 | 708 | const cte_slot_index = self.comptime_exprs.items.len; |
| 727 | 709 | try self.comptime_exprs.append(self.arena, .{ |
| 728 | 710 | .code = path, |
| 729 | | .typeRef = .{ .type = @enumToInt(DocData.DocTypeKinds.Type) }, |
| 730 | 711 | }); |
| 731 | 712 | return DocData.WalkResult{ |
| 732 | | .comptimeExpr = cte_slot_index, |
| 713 | .typeRef = .{ .type = @enumToInt(Ref.type_type) }, |
| 714 | .expr = .{ .comptimeExpr = cte_slot_index }, |
| 733 | 715 | }; |
| 734 | 716 | } |
| 735 | 717 | |
| 736 | 718 | const new_file = self.module.importFile(file, path) catch unreachable; |
| 737 | 719 | const result = try self.files.getOrPut(self.arena, new_file.file); |
| 738 | 720 | if (result.found_existing) { |
| 739 | | return DocData.WalkResult{ .type = result.value_ptr.* }; |
| 721 | return DocData.WalkResult{ |
| 722 | .typeRef = .{ .type = @enumToInt(Ref.type_type) }, |
| 723 | .expr = .{ .type = result.value_ptr.* }, |
| 724 | }; |
| 740 | 725 | } |
| 741 | 726 | |
| 742 | 727 | result.value_ptr.* = self.types.items.len; |
| ... | ... | @@ -745,18 +730,38 @@ fn walkInstruction( |
| 745 | 730 | .parent = null, |
| 746 | 731 | .enclosing_type = self.types.items.len, |
| 747 | 732 | }; |
| 748 | | const new_file_walk_result = self.walkInstruction( |
| 733 | |
| 734 | return self.walkInstruction( |
| 749 | 735 | new_file.file, |
| 750 | 736 | &new_scope, |
| 751 | 737 | Zir.main_struct_inst, |
| 738 | need_type, |
| 752 | 739 | ); |
| 753 | | |
| 754 | | return new_file_walk_result; |
| 755 | 740 | }, |
| 756 | 741 | .str => { |
| 757 | | const str = data[inst_index].str; |
| 742 | const str = data[inst_index].str.get(file.zir); |
| 743 | |
| 744 | const tRef: ?DocData.Expr = if (!need_type) null else blk: { |
| 745 | const arrTypeId = self.types.items.len; |
| 746 | try self.types.append(self.arena, .{ |
| 747 | .Array = .{ |
| 748 | .len = .{ .int = .{ .value = str.len } }, |
| 749 | .child = .{ .type = @enumToInt(Ref.u8_type) }, |
| 750 | }, |
| 751 | }); |
| 752 | const ptrTypeId = self.types.items.len; |
| 753 | try self.types.append(self.arena, .{ |
| 754 | .Pointer = .{ |
| 755 | .size = .One, |
| 756 | .child = .{ .type = arrTypeId }, |
| 757 | // TODO: add sentinel! |
| 758 | }, |
| 759 | }); |
| 760 | break :blk .{ .type = ptrTypeId }; |
| 761 | }; |
| 758 | 762 | return DocData.WalkResult{ |
| 759 | | .string = str.get(file.zir), |
| 763 | .typeRef = tRef, |
| 764 | .expr = .{ .string = str }, |
| 760 | 765 | }; |
| 761 | 766 | }, |
| 762 | 767 | .compile_error => { |
| ... | ... | @@ -765,24 +770,23 @@ fn walkInstruction( |
| 765 | 770 | file, |
| 766 | 771 | parent_scope, |
| 767 | 772 | un_node.operand, |
| 773 | false, |
| 768 | 774 | ); |
| 769 | 775 | |
| 770 | | return DocData.WalkResult{ .compileError = operand.string }; |
| 776 | return DocData.WalkResult{ |
| 777 | .expr = .{ .compileError = operand.expr.string }, |
| 778 | }; |
| 771 | 779 | }, |
| 772 | 780 | .enum_literal => { |
| 773 | 781 | const str_tok = data[inst_index].str_tok; |
| 774 | 782 | const literal = file.zir.nullTerminatedString(str_tok.start); |
| 775 | | return DocData.WalkResult{ .enumLiteral = literal }; |
| 783 | return DocData.WalkResult{ .expr = .{ .enumLiteral = literal } }; |
| 776 | 784 | }, |
| 777 | 785 | .int => { |
| 778 | 786 | const int = data[inst_index].int; |
| 779 | | const t = try self.arena.create(DocData.WalkResult); |
| 780 | | t.* = .{ .type = @enumToInt(Ref.comptime_int_type) }; |
| 781 | 787 | return DocData.WalkResult{ |
| 782 | | .int = .{ |
| 783 | | .typeRef = t, |
| 784 | | .value = int, |
| 785 | | }, |
| 788 | .typeRef = .{ .type = @enumToInt(Ref.comptime_int_type) }, |
| 789 | .expr = .{ .int = .{ .value = int } }, |
| 786 | 790 | }; |
| 787 | 791 | }, |
| 788 | 792 | .error_union_type => { |
| ... | ... | @@ -790,20 +794,23 @@ fn walkInstruction( |
| 790 | 794 | const extra = file.zir.extraData(Zir.Inst.Bin, pl_node.payload_index); |
| 791 | 795 | |
| 792 | 796 | // TODO: return the actual error union instread of cheating |
| 793 | | return self.walkRef(file, parent_scope, extra.data.rhs); |
| 797 | return self.walkRef(file, parent_scope, extra.data.rhs, need_type); |
| 794 | 798 | }, |
| 795 | 799 | .ptr_type_simple => { |
| 796 | 800 | const ptr = data[inst_index].ptr_type_simple; |
| 797 | 801 | const type_slot_index = self.types.items.len; |
| 798 | | const elem_type_ref = try self.walkRef(file, parent_scope, ptr.elem_type); |
| 802 | const elem_type_ref = try self.walkRef(file, parent_scope, ptr.elem_type, false); |
| 799 | 803 | try self.types.append(self.arena, .{ |
| 800 | 804 | .Pointer = .{ |
| 801 | 805 | .size = ptr.size, |
| 802 | | .child = elem_type_ref, |
| 806 | .child = elem_type_ref.expr, |
| 803 | 807 | }, |
| 804 | 808 | }); |
| 805 | 809 | |
| 806 | | return DocData.WalkResult{ .type = type_slot_index }; |
| 810 | return DocData.WalkResult{ |
| 811 | .typeRef = .{ .type = @enumToInt(Ref.type_type) }, |
| 812 | .expr = .{ .type = type_slot_index }, |
| 813 | }; |
| 807 | 814 | }, |
| 808 | 815 | .ptr_type => { |
| 809 | 816 | const ptr = data[inst_index].ptr_type; |
| ... | ... | @@ -814,74 +821,84 @@ fn walkInstruction( |
| 814 | 821 | file, |
| 815 | 822 | parent_scope, |
| 816 | 823 | extra.data.elem_type, |
| 824 | false, |
| 817 | 825 | ); |
| 818 | 826 | try self.types.append(self.arena, .{ |
| 819 | 827 | .Pointer = .{ |
| 820 | 828 | .size = ptr.size, |
| 821 | | .child = elem_type_ref, |
| 829 | .child = elem_type_ref.expr, |
| 822 | 830 | }, |
| 823 | 831 | }); |
| 824 | | |
| 825 | | return DocData.WalkResult{ .type = type_slot_index }; |
| 832 | return DocData.WalkResult{ |
| 833 | .typeRef = .{ .type = @enumToInt(Ref.type_type) }, |
| 834 | .expr = .{ .type = type_slot_index }, |
| 835 | }; |
| 826 | 836 | }, |
| 827 | 837 | .array_type => { |
| 828 | 838 | const bin = data[inst_index].bin; |
| 829 | | const len = try self.walkRef(file, parent_scope, bin.lhs); |
| 830 | | const child = try self.walkRef(file, parent_scope, bin.rhs); |
| 839 | const len = try self.walkRef(file, parent_scope, bin.lhs, false); |
| 840 | const child = try self.walkRef(file, parent_scope, bin.rhs, false); |
| 831 | 841 | |
| 832 | 842 | const type_slot_index = self.types.items.len; |
| 833 | 843 | try self.types.append(self.arena, .{ |
| 834 | 844 | .Array = .{ |
| 835 | | .len = len, |
| 836 | | .child = child, |
| 845 | .len = len.expr, |
| 846 | .child = child.expr, |
| 837 | 847 | }, |
| 838 | 848 | }); |
| 839 | | return DocData.WalkResult{ .type = type_slot_index }; |
| 849 | return DocData.WalkResult{ |
| 850 | .typeRef = .{ .type = @enumToInt(Ref.type_type) }, |
| 851 | .expr = .{ .type = type_slot_index }, |
| 852 | }; |
| 840 | 853 | }, |
| 841 | 854 | .array_init => { |
| 842 | 855 | const pl_node = data[inst_index].pl_node; |
| 843 | 856 | const extra = file.zir.extraData(Zir.Inst.MultiOp, pl_node.payload_index); |
| 844 | 857 | const operands = file.zir.refSlice(extra.end, extra.data.operands_len); |
| 845 | | const array_data = try self.arena.alloc(DocData.WalkResult, operands.len); |
| 858 | const array_data = try self.arena.alloc(usize, operands.len); |
| 859 | |
| 860 | // TODO: make sure that you want the array to be fully normalized for real |
| 861 | // then update this code to conform to your choice. |
| 862 | |
| 863 | var array_type: ?DocData.Expr = null; |
| 846 | 864 | for (operands) |op, idx| { |
| 847 | | array_data[idx] = try self.walkRef(file, parent_scope, op); |
| 848 | | } |
| 865 | // we only ask to figure out type info for the first element |
| 866 | // as it will be used later on to find out the array type! |
| 867 | const wr = try self.walkRef(file, parent_scope, op, idx == 0); |
| 868 | |
| 869 | if (idx == 0) { |
| 870 | array_type = wr.typeRef; |
| 871 | } |
| 849 | 872 | |
| 850 | | const at = try self.arena.create(DocData.WalkResult); |
| 851 | | at.* = .{ .type = @enumToInt(Ref.usize_type) }; |
| 873 | // We know that Zir wraps every operand in an @as expression |
| 874 | // so we want to peel it away and only save the target type |
| 875 | // once, since we need it later to define the array type. |
| 876 | array_data[idx] = wr.expr.as.exprArg; |
| 877 | } |
| 852 | 878 | |
| 853 | 879 | const type_slot_index = self.types.items.len; |
| 854 | 880 | try self.types.append(self.arena, .{ |
| 855 | 881 | .Array = .{ |
| 856 | 882 | .len = .{ |
| 857 | 883 | .int = .{ |
| 858 | | .typeRef = at, |
| 859 | 884 | .value = operands.len, |
| 860 | 885 | .negated = false, |
| 861 | 886 | }, |
| 862 | 887 | }, |
| 863 | | .child = try self.typeOfWalkResult(array_data[0]), |
| 888 | .child = array_type.?, |
| 864 | 889 | }, |
| 865 | 890 | }); |
| 866 | 891 | |
| 867 | | const t = try self.arena.create(DocData.WalkResult); |
| 868 | | t.* = .{ .type = type_slot_index }; |
| 869 | | return DocData.WalkResult{ .array = .{ |
| 870 | | .typeRef = t, |
| 871 | | .data = array_data, |
| 872 | | } }; |
| 892 | return DocData.WalkResult{ |
| 893 | .typeRef = .{ .type = type_slot_index }, |
| 894 | .expr = .{ .array = array_data }, |
| 895 | }; |
| 873 | 896 | }, |
| 874 | 897 | .float => { |
| 875 | 898 | const float = data[inst_index].float; |
| 876 | | |
| 877 | | const t = try self.arena.create(DocData.WalkResult); |
| 878 | | t.* = .{ .type = @enumToInt(Ref.comptime_float_type) }; |
| 879 | | |
| 880 | 899 | return DocData.WalkResult{ |
| 881 | | .float = .{ |
| 882 | | .typeRef = t, |
| 883 | | .value = float, |
| 884 | | }, |
| 900 | .typeRef = .{ .type = @enumToInt(Ref.comptime_float_type) }, |
| 901 | .expr = .{ .float = float }, |
| 885 | 902 | }; |
| 886 | 903 | }, |
| 887 | 904 | .negate => { |
| ... | ... | @@ -890,8 +907,9 @@ fn walkInstruction( |
| 890 | 907 | file, |
| 891 | 908 | parent_scope, |
| 892 | 909 | un_node.operand, |
| 910 | need_type, |
| 893 | 911 | ); |
| 894 | | switch (operand) { |
| 912 | switch (operand.expr) { |
| 895 | 913 | .int => |*int| int.negated = true, |
| 896 | 914 | else => { |
| 897 | 915 | printWithContext( |
| ... | ... | @@ -906,75 +924,93 @@ fn walkInstruction( |
| 906 | 924 | }, |
| 907 | 925 | .size_of => { |
| 908 | 926 | const un_node = data[inst_index].un_node; |
| 909 | | var operand = try self.arena.create(DocData.WalkResult); |
| 910 | | operand.* = try self.walkRef( |
| 927 | const operand = try self.walkRef( |
| 911 | 928 | file, |
| 912 | 929 | parent_scope, |
| 913 | 930 | un_node.operand, |
| 931 | false, |
| 914 | 932 | ); |
| 915 | | return DocData.WalkResult{ .sizeOf = operand }; |
| 933 | const operand_index = self.exprs.items.len; |
| 934 | try self.exprs.append(self.arena, operand.expr); |
| 935 | return DocData.WalkResult{ |
| 936 | .typeRef = .{ .type = @enumToInt(Ref.comptime_int_type) }, |
| 937 | .expr = .{ .sizeOf = operand_index }, |
| 938 | }; |
| 916 | 939 | }, |
| 917 | 940 | |
| 918 | 941 | .typeof => { |
| 919 | 942 | const un_node = data[inst_index].un_node; |
| 920 | | var operand = try self.arena.create(DocData.WalkResult); |
| 921 | | operand.* = try self.walkRef( |
| 943 | const operand = try self.walkRef( |
| 922 | 944 | file, |
| 923 | 945 | parent_scope, |
| 924 | 946 | un_node.operand, |
| 947 | need_type, |
| 925 | 948 | ); |
| 926 | | return DocData.WalkResult{ .typeOf = operand }; |
| 949 | const operand_index = self.exprs.items.len; |
| 950 | try self.exprs.append(self.arena, operand.expr); |
| 951 | |
| 952 | return DocData.WalkResult{ |
| 953 | .typeRef = operand.typeRef, |
| 954 | .expr = .{ .typeOf = operand_index }, |
| 955 | }; |
| 927 | 956 | }, |
| 928 | 957 | .as_node => { |
| 929 | 958 | const pl_node = data[inst_index].pl_node; |
| 930 | 959 | const extra = file.zir.extraData(Zir.Inst.As, pl_node.payload_index); |
| 931 | | const dest_type_walk = try self.walkRef(file, parent_scope, extra.data.dest_type); |
| 932 | | const dest_type_ref = dest_type_walk; |
| 960 | const dest_type_walk = try self.walkRef( |
| 961 | file, |
| 962 | parent_scope, |
| 963 | extra.data.dest_type, |
| 964 | false, |
| 965 | ); |
| 933 | 966 | |
| 934 | | var operand = try self.walkRef(file, parent_scope, extra.data.operand); |
| 967 | const operand = try self.walkRef( |
| 968 | file, |
| 969 | parent_scope, |
| 970 | extra.data.operand, |
| 971 | false, |
| 972 | ); |
| 973 | const operand_idx = self.exprs.items.len; |
| 974 | try self.exprs.append(self.arena, operand.expr); |
| 935 | 975 | |
| 936 | | switch (operand) { |
| 937 | | else => printWithContext( |
| 938 | | file, |
| 939 | | inst_index, |
| 940 | | "TODO: handle {s} in `walkInstruction.as_node`", |
| 941 | | .{@tagName(operand)}, |
| 942 | | ), |
| 943 | | .declRef, .refPath, .type, .string, .call, .enumLiteral => {}, |
| 944 | | // we don't do anything because up until now, |
| 945 | | // I've only seen this used as such: |
| 946 | | // @as(@as(type, Baz), .{}) |
| 947 | | // and we don't want to toss away the |
| 948 | | // decl_val information (eg by replacing it with |
| 949 | | // a WalkResult.type). |
| 950 | | .comptimeExpr => { |
| 951 | | self.comptime_exprs.items[operand.comptimeExpr].typeRef = dest_type_ref; |
| 952 | | }, |
| 953 | | .int => operand.int.typeRef.* = dest_type_ref, |
| 954 | | .@"struct" => operand.@"struct".typeRef.* = dest_type_ref, |
| 955 | | .@"undefined" => operand.@"undefined".* = dest_type_ref, |
| 956 | | } |
| 976 | const dest_type_idx = self.exprs.items.len; |
| 977 | try self.exprs.append(self.arena, dest_type_walk.expr); |
| 957 | 978 | |
| 958 | | return operand; |
| 979 | // TODO: there's something wrong with how both `as` and `WalkrResult` |
| 980 | // try to store type information. |
| 981 | return DocData.WalkResult{ |
| 982 | .typeRef = dest_type_walk.expr, |
| 983 | .expr = .{ |
| 984 | .as = .{ |
| 985 | .typeRefArg = dest_type_idx, |
| 986 | .exprArg = operand_idx, |
| 987 | }, |
| 988 | }, |
| 989 | }; |
| 959 | 990 | }, |
| 960 | 991 | .optional_type => { |
| 961 | 992 | const un_node = data[inst_index].un_node; |
| 962 | | var operand: DocData.WalkResult = try self.walkRef( |
| 993 | const operand: DocData.WalkResult = try self.walkRef( |
| 963 | 994 | file, |
| 964 | 995 | parent_scope, |
| 965 | 996 | un_node.operand, |
| 997 | false, |
| 966 | 998 | ); |
| 967 | | const type_ref = operand; |
| 968 | | const res = DocData.WalkResult{ .type = self.types.items.len }; |
| 999 | |
| 1000 | const operand_idx = self.types.items.len; |
| 969 | 1001 | try self.types.append(self.arena, .{ |
| 970 | | .Optional = .{ .name = "?TODO", .child = type_ref }, |
| 1002 | .Optional = .{ .name = "?TODO", .child = operand.expr }, |
| 971 | 1003 | }); |
| 972 | | return res; |
| 1004 | |
| 1005 | return DocData.WalkResult{ |
| 1006 | .typeRef = .{ .type = @enumToInt(Ref.type_type) }, |
| 1007 | .expr = .{ .type = operand_idx }, |
| 1008 | }; |
| 973 | 1009 | }, |
| 974 | 1010 | .decl_val, .decl_ref => { |
| 975 | 1011 | const str_tok = data[inst_index].str_tok; |
| 976 | 1012 | const decls_slot_index = parent_scope.resolveDeclName(str_tok.start); |
| 977 | | return DocData.WalkResult{ .declRef = decls_slot_index }; |
| 1013 | return DocData.WalkResult{ .expr = .{ .declRef = decls_slot_index } }; |
| 978 | 1014 | }, |
| 979 | 1015 | .field_val, .field_call_bind, .field_ptr, .field_type => { |
| 980 | 1016 | // TODO: field type uses Zir.Inst.FieldType, it just happens to have the |
| ... | ... | @@ -982,7 +1018,7 @@ fn walkInstruction( |
| 982 | 1018 | const pl_node = data[inst_index].pl_node; |
| 983 | 1019 | const extra = file.zir.extraData(Zir.Inst.Field, pl_node.payload_index); |
| 984 | 1020 | |
| 985 | | var path: std.ArrayListUnmanaged(DocData.WalkResult) = .{}; |
| 1021 | var path: std.ArrayListUnmanaged(DocData.Expr) = .{}; |
| 986 | 1022 | var lhs = @enumToInt(extra.data.lhs) - Ref.typed_value_map.len; // underflow = need to handle Refs |
| 987 | 1023 | |
| 988 | 1024 | try path.append(self.arena, .{ |
| ... | ... | @@ -1006,12 +1042,13 @@ fn walkInstruction( |
| 1006 | 1042 | lhs = @enumToInt(lhs_extra.data.lhs) - Ref.typed_value_map.len; // underflow = need to handle Refs |
| 1007 | 1043 | } |
| 1008 | 1044 | |
| 1009 | | const wr = try self.walkInstruction(file, parent_scope, lhs); |
| 1010 | | try path.append(self.arena, wr); |
| 1045 | // TODO: double check that we really don't need type info here |
| 1046 | const wr = try self.walkInstruction(file, parent_scope, lhs, false); |
| 1047 | try path.append(self.arena, wr.expr); |
| 1011 | 1048 | |
| 1012 | 1049 | // This way the data in `path` has the same ordering that the ref |
| 1013 | 1050 | // path has in the text: most general component first. |
| 1014 | | std.mem.reverse(DocData.WalkResult, path.items); |
| 1051 | std.mem.reverse(DocData.Expr, path.items); |
| 1015 | 1052 | |
| 1016 | 1053 | // Righ now, every element of `path` is a string except its first |
| 1017 | 1054 | // element (at index 0). We're now going to attempt to resolve each |
| ... | ... | @@ -1026,7 +1063,7 @@ fn walkInstruction( |
| 1026 | 1063 | // any value that depends on that will have to become a |
| 1027 | 1064 | // comptimeExpr. |
| 1028 | 1065 | try self.tryResolveRefPath(file, lhs, path.items); |
| 1029 | | return DocData.WalkResult{ .refPath = path.items }; |
| 1066 | return DocData.WalkResult{ .expr = .{ .refPath = path.items } }; |
| 1030 | 1067 | }, |
| 1031 | 1068 | .int_type => { |
| 1032 | 1069 | const int_type = data[inst_index].int_type; |
| ... | ... | @@ -1037,28 +1074,37 @@ fn walkInstruction( |
| 1037 | 1074 | try self.types.append(self.arena, .{ |
| 1038 | 1075 | .Int = .{ .name = name }, |
| 1039 | 1076 | }); |
| 1040 | | return DocData.WalkResult{ .type = self.types.items.len - 1 }; |
| 1077 | return DocData.WalkResult{ |
| 1078 | .typeRef = .{ .type = @enumToInt(Ref.type_type) }, |
| 1079 | .expr = .{ .type = self.types.items.len - 1 }, |
| 1080 | }; |
| 1041 | 1081 | }, |
| 1042 | 1082 | .block => { |
| 1043 | | const res = DocData.WalkResult{ .comptimeExpr = self.comptime_exprs.items.len }; |
| 1083 | const res = DocData.WalkResult{ .expr = .{ |
| 1084 | .comptimeExpr = self.comptime_exprs.items.len, |
| 1085 | } }; |
| 1044 | 1086 | try self.comptime_exprs.append(self.arena, .{ |
| 1045 | 1087 | .code = "if(banana) 1 else 0", |
| 1046 | | .typeRef = .{ .type = 0 }, |
| 1047 | 1088 | }); |
| 1048 | 1089 | return res; |
| 1049 | 1090 | }, |
| 1050 | 1091 | .block_inline => { |
| 1051 | | return self.walkRef(file, parent_scope, getBlockInlineBreak(file.zir, inst_index)); |
| 1092 | return self.walkRef( |
| 1093 | file, |
| 1094 | parent_scope, |
| 1095 | getBlockInlineBreak(file.zir, inst_index), |
| 1096 | need_type, |
| 1097 | ); |
| 1052 | 1098 | }, |
| 1053 | 1099 | .struct_init => { |
| 1054 | 1100 | const pl_node = data[inst_index].pl_node; |
| 1055 | 1101 | const extra = file.zir.extraData(Zir.Inst.StructInit, pl_node.payload_index); |
| 1056 | 1102 | const field_vals = try self.arena.alloc( |
| 1057 | | DocData.WalkResult.Struct.FieldVal, |
| 1103 | DocData.Expr.FieldVal, |
| 1058 | 1104 | extra.data.fields_len, |
| 1059 | 1105 | ); |
| 1060 | 1106 | |
| 1061 | | const type_ref = try self.arena.create(DocData.WalkResult); |
| 1107 | var type_ref: DocData.Expr = undefined; |
| 1062 | 1108 | var idx = extra.end; |
| 1063 | 1109 | for (field_vals) |*fv| { |
| 1064 | 1110 | const init_extra = file.zir.extraData(Zir.Inst.StructInit.Item, idx); |
| ... | ... | @@ -1079,19 +1125,25 @@ fn walkInstruction( |
| 1079 | 1125 | file, |
| 1080 | 1126 | parent_scope, |
| 1081 | 1127 | field_extra.data.container_type, |
| 1128 | false, |
| 1082 | 1129 | ); |
| 1083 | | type_ref.* = wr; |
| 1130 | type_ref = wr.expr; |
| 1084 | 1131 | } |
| 1085 | 1132 | break :blk file.zir.nullTerminatedString(field_extra.data.name_start); |
| 1086 | 1133 | }; |
| 1087 | | const value = try self.walkRef(file, parent_scope, init_extra.data.init); |
| 1134 | const value = try self.walkRef( |
| 1135 | file, |
| 1136 | parent_scope, |
| 1137 | init_extra.data.init, |
| 1138 | need_type, |
| 1139 | ); |
| 1088 | 1140 | fv.* = .{ .name = field_name, .val = value }; |
| 1089 | 1141 | } |
| 1090 | 1142 | |
| 1091 | | return DocData.WalkResult{ .@"struct" = .{ |
| 1143 | return DocData.WalkResult{ |
| 1092 | 1144 | .typeRef = type_ref, |
| 1093 | | .fieldVals = field_vals, |
| 1094 | | } }; |
| 1145 | .expr = .{ .@"struct" = field_vals }, |
| 1146 | }; |
| 1095 | 1147 | }, |
| 1096 | 1148 | .error_set_decl => { |
| 1097 | 1149 | const pl_node = data[inst_index].pl_node; |
| ... | ... | @@ -1122,7 +1174,10 @@ fn walkInstruction( |
| 1122 | 1174 | }, |
| 1123 | 1175 | }); |
| 1124 | 1176 | |
| 1125 | | return DocData.WalkResult{ .type = type_slot_index }; |
| 1177 | return DocData.WalkResult{ |
| 1178 | .typeRef = .{ .type = @enumToInt(Ref.type_type) }, |
| 1179 | .expr = .{ .type = type_slot_index }, |
| 1180 | }; |
| 1126 | 1181 | }, |
| 1127 | 1182 | .param_anytype => { |
| 1128 | 1183 | // Analysis of anytype function params happens in `.func`. |
| ... | ... | @@ -1134,9 +1189,8 @@ fn walkInstruction( |
| 1134 | 1189 | const cte_slot_index = self.comptime_exprs.items.len; |
| 1135 | 1190 | try self.comptime_exprs.append(self.arena, .{ |
| 1136 | 1191 | .code = name, |
| 1137 | | .typeRef = .{ .type = @enumToInt(DocData.DocTypeKinds.ComptimeExpr) }, |
| 1138 | 1192 | }); |
| 1139 | | return DocData.WalkResult{ .comptimeExpr = cte_slot_index }; |
| 1193 | return DocData.WalkResult{ .expr = .{ .comptimeExpr = cte_slot_index } }; |
| 1140 | 1194 | }, |
| 1141 | 1195 | .param, .param_comptime => { |
| 1142 | 1196 | // See .param_anytype for more information. |
| ... | ... | @@ -1146,41 +1200,46 @@ fn walkInstruction( |
| 1146 | 1200 | const cte_slot_index = self.comptime_exprs.items.len; |
| 1147 | 1201 | try self.comptime_exprs.append(self.arena, .{ |
| 1148 | 1202 | .code = name, |
| 1149 | | .typeRef = .{ .type = @enumToInt(DocData.DocTypeKinds.ComptimeExpr) }, |
| 1150 | 1203 | }); |
| 1151 | | return DocData.WalkResult{ .comptimeExpr = cte_slot_index }; |
| 1204 | return DocData.WalkResult{ .expr = .{ .comptimeExpr = cte_slot_index } }; |
| 1152 | 1205 | }, |
| 1153 | 1206 | .call => { |
| 1154 | 1207 | const pl_node = data[inst_index].pl_node; |
| 1155 | 1208 | const extra = file.zir.extraData(Zir.Inst.Call, pl_node.payload_index); |
| 1156 | 1209 | |
| 1157 | | const callee = try self.walkRef(file, parent_scope, extra.data.callee); |
| 1210 | const callee = try self.walkRef(file, parent_scope, extra.data.callee, need_type); |
| 1158 | 1211 | |
| 1159 | 1212 | const args_len = extra.data.flags.args_len; |
| 1160 | | var args = try self.arena.alloc(DocData.WalkResult, args_len); |
| 1213 | var args = try self.arena.alloc(DocData.Expr, args_len); |
| 1161 | 1214 | const arg_refs = file.zir.refSlice(extra.end, args_len); |
| 1162 | 1215 | for (arg_refs) |ref, idx| { |
| 1163 | | args[idx] = try self.walkRef(file, parent_scope, ref); |
| 1216 | // TODO: consider toggling need_type to true if we ever want |
| 1217 | // to show discrepancies between the types of provided |
| 1218 | // arguments and the types declared in the function |
| 1219 | // signature for its parameters. |
| 1220 | const wr = try self.walkRef(file, parent_scope, ref, false); |
| 1221 | args[idx] = wr.expr; |
| 1164 | 1222 | } |
| 1165 | 1223 | |
| 1166 | | // TODO: see if we can ever do something better than just always |
| 1167 | | // resolve function calls to a comptimeExpr. |
| 1168 | 1224 | const cte_slot_index = self.comptime_exprs.items.len; |
| 1169 | 1225 | try self.comptime_exprs.append(self.arena, .{ |
| 1170 | 1226 | .code = "func call", |
| 1171 | | .typeRef = .{ |
| 1172 | | .type = @enumToInt(DocData.DocTypeKinds.ComptimeExpr), |
| 1173 | | }, // TODO: extract return type from callee when available |
| 1174 | 1227 | }); |
| 1175 | 1228 | |
| 1176 | 1229 | const call_slot_index = self.calls.items.len; |
| 1177 | 1230 | try self.calls.append(self.arena, .{ |
| 1178 | | .func = callee, |
| 1231 | .func = callee.expr, |
| 1179 | 1232 | .args = args, |
| 1180 | 1233 | .ret = .{ .comptimeExpr = cte_slot_index }, |
| 1181 | 1234 | }); |
| 1182 | 1235 | |
| 1183 | | return DocData.WalkResult{ .call = call_slot_index }; |
| 1236 | return DocData.WalkResult{ |
| 1237 | .typeRef = if (callee.typeRef) |tr| switch (tr) { |
| 1238 | .type => |func_type_idx| self.types.items[func_type_idx].Fn.ret, |
| 1239 | else => null, |
| 1240 | } else null, |
| 1241 | .expr = .{ .call = call_slot_index }, |
| 1242 | }; |
| 1184 | 1243 | }, |
| 1185 | 1244 | .func, .func_inferred => { |
| 1186 | 1245 | const type_slot_index = self.types.items.len; |
| ... | ... | @@ -1208,42 +1267,13 @@ fn walkInstruction( |
| 1208 | 1267 | }, |
| 1209 | 1268 | |
| 1210 | 1269 | .opaque_decl => return self.cteTodo("opaque {...}"), |
| 1211 | | // .func => { |
| 1212 | | // const type_slot_index = self.types.items.len; |
| 1213 | | // try self.types.append(self.arena, .{ .Unanalyzed = {} }); |
| 1214 | | // |
| 1215 | | // const result = try self.analyzeFunction( |
| 1216 | | // file, |
| 1217 | | // parent_scope, |
| 1218 | | // inst_index, |
| 1219 | | // self_ast_node_index, |
| 1220 | | // type_slot_index, |
| 1221 | | // ); |
| 1222 | | // if (self.ref_paths_pending_on_types.get(type_slot_index)) |paths| { |
| 1223 | | // for (paths.items) |resume_info| { |
| 1224 | | // try self.tryResolveRefPath( |
| 1225 | | // resume_info.file, |
| 1226 | | // inst_index, |
| 1227 | | // resume_info.ref_path, |
| 1228 | | // ); |
| 1229 | | // } |
| 1230 | | // |
| 1231 | | // _ = self.ref_paths_pending_on_types.remove(type_slot_index); |
| 1232 | | // // TODO: we should deallocate the arraylist that holds all the |
| 1233 | | // // decl paths. not doing it now since it's arena-allocated |
| 1234 | | // // anyway, but maybe we should put it elsewhere. |
| 1235 | | // } |
| 1236 | | // return result; |
| 1237 | | // }, |
| 1238 | 1270 | .variable => { |
| 1239 | 1271 | const small = @bitCast(Zir.Inst.ExtendedVar.Small, extended.small); |
| 1240 | 1272 | var extra_index: usize = extended.operand; |
| 1241 | 1273 | if (small.has_lib_name) extra_index += 1; |
| 1242 | 1274 | if (small.has_align) extra_index += 1; |
| 1243 | 1275 | |
| 1244 | | const value: DocData.WalkResult = |
| 1245 | | if (small.has_init) |
| 1246 | | .{ .void = {} } else .{ .void = {} }; |
| 1276 | const value: DocData.WalkResult = if (small.has_init) .{ .expr = .{ .void = {} } } else .{ .expr = .{ .void = {} } }; |
| 1247 | 1277 | |
| 1248 | 1278 | return value; |
| 1249 | 1279 | }, |
| ... | ... | @@ -1322,10 +1352,9 @@ fn walkInstruction( |
| 1322 | 1352 | extra_index, |
| 1323 | 1353 | ); |
| 1324 | 1354 | |
| 1325 | | // const body = file.zir.extra[extra_index..][0..body_len]; |
| 1326 | 1355 | extra_index += body_len; |
| 1327 | 1356 | |
| 1328 | | var field_type_refs = try std.ArrayListUnmanaged(DocData.WalkResult).initCapacity( |
| 1357 | var field_type_refs = try std.ArrayListUnmanaged(DocData.Expr).initCapacity( |
| 1329 | 1358 | self.arena, |
| 1330 | 1359 | fields_len, |
| 1331 | 1360 | ); |
| ... | ... | @@ -1369,7 +1398,10 @@ fn walkInstruction( |
| 1369 | 1398 | // anyway, but maybe we should put it elsewhere. |
| 1370 | 1399 | } |
| 1371 | 1400 | |
| 1372 | | return DocData.WalkResult{ .type = type_slot_index }; |
| 1401 | return DocData.WalkResult{ |
| 1402 | .typeRef = .{ .type = @enumToInt(Ref.type_type) }, |
| 1403 | .expr = .{ .type = type_slot_index }, |
| 1404 | }; |
| 1373 | 1405 | }, |
| 1374 | 1406 | .enum_decl => { |
| 1375 | 1407 | const type_slot_index = self.types.items.len; |
| ... | ... | @@ -1516,8 +1548,10 @@ fn walkInstruction( |
| 1516 | 1548 | // decl paths. not doing it now since it's arena-allocated |
| 1517 | 1549 | // anyway, but maybe we should put it elsewhere. |
| 1518 | 1550 | } |
| 1519 | | |
| 1520 | | return DocData.WalkResult{ .type = type_slot_index }; |
| 1551 | return DocData.WalkResult{ |
| 1552 | .typeRef = .{ .type = @enumToInt(Ref.type_type) }, |
| 1553 | .expr = .{ .type = type_slot_index }, |
| 1554 | }; |
| 1521 | 1555 | }, |
| 1522 | 1556 | .struct_decl => { |
| 1523 | 1557 | const type_slot_index = self.types.items.len; |
| ... | ... | @@ -1590,7 +1624,7 @@ fn walkInstruction( |
| 1590 | 1624 | // const body = file.zir.extra[extra_index..][0..body_len]; |
| 1591 | 1625 | extra_index += body_len; |
| 1592 | 1626 | |
| 1593 | | var field_type_refs: std.ArrayListUnmanaged(DocData.WalkResult) = .{}; |
| 1627 | var field_type_refs: std.ArrayListUnmanaged(DocData.Expr) = .{}; |
| 1594 | 1628 | var field_name_indexes: std.ArrayListUnmanaged(usize) = .{}; |
| 1595 | 1629 | try self.collectStructFieldInfo( |
| 1596 | 1630 | file, |
| ... | ... | @@ -1626,11 +1660,16 @@ fn walkInstruction( |
| 1626 | 1660 | // decl paths. not doing it now since it's arena-allocated |
| 1627 | 1661 | // anyway, but maybe we should put it elsewhere. |
| 1628 | 1662 | } |
| 1629 | | |
| 1630 | | return DocData.WalkResult{ .type = type_slot_index }; |
| 1663 | return DocData.WalkResult{ |
| 1664 | .typeRef = .{ .type = @enumToInt(Ref.type_type) }, |
| 1665 | .expr = .{ .type = type_slot_index }, |
| 1666 | }; |
| 1631 | 1667 | }, |
| 1632 | 1668 | .this => { |
| 1633 | | return DocData.WalkResult{ .this = parent_scope.enclosing_type }; |
| 1669 | return DocData.WalkResult{ |
| 1670 | .typeRef = .{ .type = @enumToInt(Ref.type_type) }, |
| 1671 | .expr = .{ .this = parent_scope.enclosing_type }, |
| 1672 | }; |
| 1634 | 1673 | }, |
| 1635 | 1674 | } |
| 1636 | 1675 | }, |
| ... | ... | @@ -1793,7 +1832,7 @@ fn walkDecls( |
| 1793 | 1832 | .name = "test", |
| 1794 | 1833 | .isTest = true, |
| 1795 | 1834 | .src = ast_node_index, |
| 1796 | | .value = .{ .type = 0 }, |
| 1835 | .value = .{ .expr = .{ .type = 0 } }, |
| 1797 | 1836 | .kind = "const", |
| 1798 | 1837 | }; |
| 1799 | 1838 | continue; |
| ... | ... | @@ -1827,9 +1866,9 @@ fn walkDecls( |
| 1827 | 1866 | }; |
| 1828 | 1867 | |
| 1829 | 1868 | const walk_result = if (is_test) // TODO: decide if tests should show up at all |
| 1830 | | DocData.WalkResult{ .void = {} } |
| 1869 | DocData.WalkResult{ .expr = .{ .void = {} } } |
| 1831 | 1870 | else |
| 1832 | | try self.walkInstruction(file, scope, value_index); |
| 1871 | try self.walkInstruction(file, scope, value_index, true); |
| 1833 | 1872 | |
| 1834 | 1873 | if (is_pub) { |
| 1835 | 1874 | try decl_indexes.append(self.arena, decls_slot_index); |
| ... | ... | @@ -1857,7 +1896,7 @@ fn walkDecls( |
| 1857 | 1896 | .name = name, |
| 1858 | 1897 | .isTest = is_test, |
| 1859 | 1898 | .src = ast_node_index, |
| 1860 | | // .typeRef = decl_type_ref, |
| 1899 | //.typeRef = decl_type_ref, |
| 1861 | 1900 | .value = walk_result, |
| 1862 | 1901 | .kind = "const", // find where this information can be found |
| 1863 | 1902 | }; |
| ... | ... | @@ -1906,7 +1945,7 @@ fn tryResolveRefPath( |
| 1906 | 1945 | /// File from which the decl path originates. |
| 1907 | 1946 | file: *File, |
| 1908 | 1947 | inst_index: usize, // used only for panicWithContext |
| 1909 | | path: []DocData.WalkResult, |
| 1948 | path: []DocData.Expr, |
| 1910 | 1949 | ) error{OutOfMemory}!void { |
| 1911 | 1950 | var i: usize = 0; |
| 1912 | 1951 | outer: while (i < path.len - 1) : (i += 1) { |
| ... | ... | @@ -1922,7 +1961,7 @@ fn tryResolveRefPath( |
| 1922 | 1961 | .declRef => |decl_index| { |
| 1923 | 1962 | const decl = self.decls.items[decl_index]; |
| 1924 | 1963 | if (decl._analyzed) { |
| 1925 | | resolved_parent = decl.value; |
| 1964 | resolved_parent = decl.value.expr; |
| 1926 | 1965 | continue; |
| 1927 | 1966 | } |
| 1928 | 1967 | |
| ... | ... | @@ -2004,7 +2043,7 @@ fn tryResolveRefPath( |
| 2004 | 2043 | "TODO: handle `{s}`in tryResolveRefPath\nInfo: {}", |
| 2005 | 2044 | .{ @tagName(resolved_parent), resolved_parent }, |
| 2006 | 2045 | ); |
| 2007 | | path[i + 1] = try self.cteTodo("match failure"); |
| 2046 | path[i + 1] = (try self.cteTodo("match failure")).expr; |
| 2008 | 2047 | continue :outer; |
| 2009 | 2048 | }, |
| 2010 | 2049 | .comptimeExpr, .call => { |
| ... | ... | @@ -2088,7 +2127,7 @@ fn tryResolveRefPath( |
| 2088 | 2127 | .{child_string}, |
| 2089 | 2128 | ); |
| 2090 | 2129 | |
| 2091 | | path[i + 1] = try self.cteTodo("match failure"); |
| 2130 | path[i + 1] = (try self.cteTodo("match failure")).expr; |
| 2092 | 2131 | continue :outer; |
| 2093 | 2132 | }, |
| 2094 | 2133 | .Union => |t_union| { |
| ... | ... | @@ -2134,7 +2173,7 @@ fn tryResolveRefPath( |
| 2134 | 2173 | "failed to match `{s}` in union", |
| 2135 | 2174 | .{child_string}, |
| 2136 | 2175 | ); |
| 2137 | | path[i + 1] = try self.cteTodo("match failure"); |
| 2176 | path[i + 1] = (try self.cteTodo("match failure")).expr; |
| 2138 | 2177 | continue :outer; |
| 2139 | 2178 | }, |
| 2140 | 2179 | |
| ... | ... | @@ -2181,7 +2220,7 @@ fn tryResolveRefPath( |
| 2181 | 2220 | "failed to match `{s}` in struct", |
| 2182 | 2221 | .{child_string}, |
| 2183 | 2222 | ); |
| 2184 | | path[i + 1] = try self.cteTodo("match failure"); |
| 2223 | path[i + 1] = (try self.cteTodo("match failure")).expr; |
| 2185 | 2224 | continue :outer; |
| 2186 | 2225 | }, |
| 2187 | 2226 | }, |
| ... | ... | @@ -2214,7 +2253,7 @@ fn analyzeFunction( |
| 2214 | 2253 | const fn_info = file.zir.getFnInfo(@intCast(u32, inst_index)); |
| 2215 | 2254 | |
| 2216 | 2255 | try self.ast_nodes.ensureUnusedCapacity(self.arena, fn_info.total_params_len); |
| 2217 | | var param_type_refs = try std.ArrayListUnmanaged(DocData.WalkResult).initCapacity( |
| 2256 | var param_type_refs = try std.ArrayListUnmanaged(DocData.Expr).initCapacity( |
| 2218 | 2257 | self.arena, |
| 2219 | 2258 | fn_info.total_params_len, |
| 2220 | 2259 | ); |
| ... | ... | @@ -2246,7 +2285,7 @@ fn analyzeFunction( |
| 2246 | 2285 | }); |
| 2247 | 2286 | |
| 2248 | 2287 | param_type_refs.appendAssumeCapacity( |
| 2249 | | DocData.WalkResult{ .@"anytype" = {} }, |
| 2288 | DocData.Expr{ .@"anytype" = {} }, |
| 2250 | 2289 | ); |
| 2251 | 2290 | }, |
| 2252 | 2291 | .param, .param_comptime => { |
| ... | ... | @@ -2267,9 +2306,9 @@ fn analyzeFunction( |
| 2267 | 2306 | |
| 2268 | 2307 | const break_index = file.zir.extra[extra.end..][extra.data.body_len - 1]; |
| 2269 | 2308 | const break_operand = data[break_index].@"break".operand; |
| 2270 | | const param_type_ref = try self.walkRef(file, scope, break_operand); |
| 2309 | const param_type_ref = try self.walkRef(file, scope, break_operand, false); |
| 2271 | 2310 | |
| 2272 | | param_type_refs.appendAssumeCapacity(param_type_ref); |
| 2311 | param_type_refs.appendAssumeCapacity(param_type_ref.expr); |
| 2273 | 2312 | }, |
| 2274 | 2313 | } |
| 2275 | 2314 | } |
| ... | ... | @@ -2278,7 +2317,7 @@ fn analyzeFunction( |
| 2278 | 2317 | const ret_type_ref = blk: { |
| 2279 | 2318 | const last_instr_index = fn_info.ret_ty_body[fn_info.ret_ty_body.len - 1]; |
| 2280 | 2319 | const break_operand = data[last_instr_index].@"break".operand; |
| 2281 | | const wr = try self.walkRef(file, scope, break_operand); |
| 2320 | const wr = try self.walkRef(file, scope, break_operand, false); |
| 2282 | 2321 | break :blk wr; |
| 2283 | 2322 | }; |
| 2284 | 2323 | |
| ... | ... | @@ -2288,10 +2327,13 @@ fn analyzeFunction( |
| 2288 | 2327 | .name = "todo_name func", |
| 2289 | 2328 | .src = self_ast_node_index, |
| 2290 | 2329 | .params = param_type_refs.items, |
| 2291 | | .ret = ret_type_ref, |
| 2330 | .ret = ret_type_ref.expr, |
| 2292 | 2331 | }, |
| 2293 | 2332 | }; |
| 2294 | | return DocData.WalkResult{ .type = type_slot_index }; |
| 2333 | return DocData.WalkResult{ |
| 2334 | .typeRef = .{ .type = @enumToInt(Ref.type_type) }, |
| 2335 | .expr = .{ .type = type_slot_index }, |
| 2336 | }; |
| 2295 | 2337 | } |
| 2296 | 2338 | |
| 2297 | 2339 | fn collectUnionFieldInfo( |
| ... | ... | @@ -2299,7 +2341,7 @@ fn collectUnionFieldInfo( |
| 2299 | 2341 | file: *File, |
| 2300 | 2342 | scope: *Scope, |
| 2301 | 2343 | fields_len: usize, |
| 2302 | | field_type_refs: *std.ArrayListUnmanaged(DocData.WalkResult), |
| 2344 | field_type_refs: *std.ArrayListUnmanaged(DocData.Expr), |
| 2303 | 2345 | field_name_indexes: *std.ArrayListUnmanaged(usize), |
| 2304 | 2346 | ei: usize, |
| 2305 | 2347 | ) !void { |
| ... | ... | @@ -2344,8 +2386,8 @@ fn collectUnionFieldInfo( |
| 2344 | 2386 | |
| 2345 | 2387 | // type |
| 2346 | 2388 | { |
| 2347 | | const walk_result = try self.walkRef(file, scope, field_type); |
| 2348 | | try field_type_refs.append(self.arena, walk_result); |
| 2389 | const walk_result = try self.walkRef(file, scope, field_type, false); |
| 2390 | try field_type_refs.append(self.arena, walk_result.expr); |
| 2349 | 2391 | } |
| 2350 | 2392 | |
| 2351 | 2393 | // ast node |
| ... | ... | @@ -2368,7 +2410,7 @@ fn collectStructFieldInfo( |
| 2368 | 2410 | file: *File, |
| 2369 | 2411 | scope: *Scope, |
| 2370 | 2412 | fields_len: usize, |
| 2371 | | field_type_refs: *std.ArrayListUnmanaged(DocData.WalkResult), |
| 2413 | field_type_refs: *std.ArrayListUnmanaged(DocData.Expr), |
| 2372 | 2414 | field_name_indexes: *std.ArrayListUnmanaged(usize), |
| 2373 | 2415 | ei: usize, |
| 2374 | 2416 | ) !void { |
| ... | ... | @@ -2410,8 +2452,8 @@ fn collectStructFieldInfo( |
| 2410 | 2452 | |
| 2411 | 2453 | // type |
| 2412 | 2454 | { |
| 2413 | | const walk_result = try self.walkRef(file, scope, field_type); |
| 2414 | | try field_type_refs.append(self.arena, walk_result); |
| 2455 | const walk_result = try self.walkRef(file, scope, field_type, false); |
| 2456 | try field_type_refs.append(self.arena, walk_result.expr); |
| 2415 | 2457 | } |
| 2416 | 2458 | |
| 2417 | 2459 | // ast node |
| ... | ... | @@ -2436,13 +2478,17 @@ fn walkRef( |
| 2436 | 2478 | file: *File, |
| 2437 | 2479 | parent_scope: *Scope, |
| 2438 | 2480 | ref: Ref, |
| 2481 | need_type: bool, // true when the caller needs also a typeRef for the return value |
| 2439 | 2482 | ) !DocData.WalkResult { |
| 2440 | 2483 | const enum_value = @enumToInt(ref); |
| 2441 | 2484 | if (enum_value <= @enumToInt(Ref.anyerror_void_error_union_type)) { |
| 2442 | 2485 | // We can just return a type that indexes into `types` with the |
| 2443 | 2486 | // enum value because in the beginning we pre-filled `types` with |
| 2444 | 2487 | // the types that are listed in `Ref`. |
| 2445 | | return DocData.WalkResult{ .type = enum_value }; |
| 2488 | return DocData.WalkResult{ |
| 2489 | .typeRef = .{ .type = @enumToInt(std.builtin.TypeId.Type) }, |
| 2490 | .expr = .{ .type = enum_value }, |
| 2491 | }; |
| 2446 | 2492 | } else if (enum_value < Ref.typed_value_map.len) { |
| 2447 | 2493 | switch (ref) { |
| 2448 | 2494 | else => { |
| ... | ... | @@ -2451,69 +2497,62 @@ fn walkRef( |
| 2451 | 2497 | }); |
| 2452 | 2498 | }, |
| 2453 | 2499 | .undef => { |
| 2454 | | var t = try self.arena.create(DocData.WalkResult); |
| 2455 | | t.* = .void; |
| 2456 | | |
| 2457 | | return DocData.WalkResult{ .@"undefined" = t }; |
| 2500 | return DocData.WalkResult{ .expr = .@"undefined" }; |
| 2458 | 2501 | }, |
| 2459 | 2502 | .zero => { |
| 2460 | | var t = try self.arena.create(DocData.WalkResult); |
| 2461 | | t.* = .{ .type = @enumToInt(Ref.comptime_int_type) }; |
| 2462 | | return DocData.WalkResult{ .int = .{ |
| 2463 | | .typeRef = t, |
| 2464 | | .value = 0, |
| 2465 | | } }; |
| 2503 | return DocData.WalkResult{ |
| 2504 | .typeRef = .{ .type = @enumToInt(Ref.comptime_int_type) }, |
| 2505 | .expr = .{ .int = .{ .value = 0 } }, |
| 2506 | }; |
| 2466 | 2507 | }, |
| 2467 | 2508 | .one => { |
| 2468 | | var t = try self.arena.create(DocData.WalkResult); |
| 2469 | | t.* = .{ .type = @enumToInt(Ref.comptime_int_type) }; |
| 2470 | | return DocData.WalkResult{ .int = .{ |
| 2471 | | .typeRef = t, |
| 2472 | | .value = 1, |
| 2473 | | } }; |
| 2509 | return DocData.WalkResult{ |
| 2510 | .typeRef = .{ .type = @enumToInt(Ref.comptime_int_type) }, |
| 2511 | .expr = .{ .int = .{ .value = 1 } }, |
| 2512 | }; |
| 2474 | 2513 | }, |
| 2475 | 2514 | |
| 2476 | 2515 | .void_value => { |
| 2477 | | return DocData.WalkResult{ .void = {} }; |
| 2516 | return DocData.WalkResult{ |
| 2517 | .typeRef = .{ .type = @enumToInt(Ref.void_type) }, |
| 2518 | .expr = .{ .void = {} }, |
| 2519 | }; |
| 2478 | 2520 | }, |
| 2479 | 2521 | .unreachable_value => { |
| 2480 | | return DocData.WalkResult{ .@"unreachable" = {} }; |
| 2522 | return DocData.WalkResult{ |
| 2523 | .typeRef = .{ .type = @enumToInt(Ref.noreturn_type) }, |
| 2524 | .expr = .{ .@"unreachable" = {} }, |
| 2525 | }; |
| 2481 | 2526 | }, |
| 2482 | 2527 | .null_value => { |
| 2483 | | var t = try self.arena.create(DocData.WalkResult); |
| 2484 | | t.* = .void; |
| 2485 | | return DocData.WalkResult{ .@"null" = t }; |
| 2528 | return DocData.WalkResult{ .expr = .@"null" }; |
| 2486 | 2529 | }, |
| 2487 | 2530 | .bool_true => { |
| 2488 | | return DocData.WalkResult{ .bool = true }; |
| 2531 | return DocData.WalkResult{ |
| 2532 | .typeRef = .{ .type = @enumToInt(Ref.bool_type) }, |
| 2533 | .expr = .{ .bool = true }, |
| 2534 | }; |
| 2489 | 2535 | }, |
| 2490 | 2536 | .bool_false => { |
| 2491 | | return DocData.WalkResult{ .bool = false }; |
| 2537 | return DocData.WalkResult{ |
| 2538 | .typeRef = .{ .type = @enumToInt(Ref.bool_type) }, |
| 2539 | .expr = .{ .bool = false }, |
| 2540 | }; |
| 2492 | 2541 | }, |
| 2493 | 2542 | .empty_struct => { |
| 2494 | | var t = try self.arena.create(DocData.WalkResult); |
| 2495 | | t.* = .void; |
| 2496 | | |
| 2497 | | return DocData.WalkResult{ .@"struct" = .{ |
| 2498 | | .typeRef = t, |
| 2499 | | .fieldVals = &.{}, |
| 2500 | | } }; |
| 2543 | return DocData.WalkResult{ .expr = .{ .@"struct" = &.{} } }; |
| 2501 | 2544 | }, |
| 2502 | 2545 | .zero_usize => { |
| 2503 | | var t = try self.arena.create(DocData.WalkResult); |
| 2504 | | t.* = .{ .type = @enumToInt(Ref.usize_type) }; |
| 2505 | | return DocData.WalkResult{ .int = .{ |
| 2506 | | .typeRef = t, |
| 2507 | | .value = 0, |
| 2508 | | } }; |
| 2546 | return DocData.WalkResult{ |
| 2547 | .typeRef = .{ .type = @enumToInt(Ref.usize_type) }, |
| 2548 | .expr = .{ .int = .{ .value = 0 } }, |
| 2549 | }; |
| 2509 | 2550 | }, |
| 2510 | 2551 | .one_usize => { |
| 2511 | | var t = try self.arena.create(DocData.WalkResult); |
| 2512 | | t.* = .{ .type = @enumToInt(Ref.usize_type) }; |
| 2513 | | return DocData.WalkResult{ .int = .{ |
| 2514 | | .typeRef = t, |
| 2515 | | .value = 1, |
| 2516 | | } }; |
| 2552 | return DocData.WalkResult{ |
| 2553 | .typeRef = .{ .type = @enumToInt(Ref.usize_type) }, |
| 2554 | .expr = .{ .int = .{ .value = 1 } }, |
| 2555 | }; |
| 2517 | 2556 | }, |
| 2518 | 2557 | // TODO: dunno what to do with those |
| 2519 | 2558 | // .calling_convention_c => { |
| ... | ... | @@ -2537,29 +2576,10 @@ fn walkRef( |
| 2537 | 2576 | } |
| 2538 | 2577 | } else { |
| 2539 | 2578 | const zir_index = enum_value - Ref.typed_value_map.len; |
| 2540 | | return self.walkInstruction(file, parent_scope, zir_index); |
| 2579 | return self.walkInstruction(file, parent_scope, zir_index, need_type); |
| 2541 | 2580 | } |
| 2542 | 2581 | } |
| 2543 | 2582 | |
| 2544 | | /// Given a WalkResult, tries to find its type. |
| 2545 | | /// Used to analyze instructions like `array_init`, which require us to |
| 2546 | | /// inspect its first element to find out the array type. |
| 2547 | | fn typeOfWalkResult(self: *Autodoc, wr: DocData.WalkResult) !DocData.WalkResult { |
| 2548 | | return switch (wr) { |
| 2549 | | else => { |
| 2550 | | std.debug.print( |
| 2551 | | "TODO: handle `{s}` in typeOfWalkResult\n", |
| 2552 | | .{@tagName(wr)}, |
| 2553 | | ); |
| 2554 | | return self.cteTodo(@tagName(wr)); |
| 2555 | | }, |
| 2556 | | .type => .{ .type = @enumToInt(DocData.DocTypeKinds.Type) }, |
| 2557 | | .int => |v| v.typeRef.*, |
| 2558 | | .float => |v| v.typeRef.*, |
| 2559 | | .array => |v| v.typeRef.*, |
| 2560 | | }; |
| 2561 | | } |
| 2562 | | |
| 2563 | 2583 | fn getBlockInlineBreak(zir: Zir, inst_index: usize) Zir.Inst.Ref { |
| 2564 | 2584 | const tags = zir.instructions.items(.tag); |
| 2565 | 2585 | const data = zir.instructions.items(.data); |
| ... | ... | @@ -2585,7 +2605,6 @@ fn cteTodo(self: *Autodoc, msg: []const u8) error{OutOfMemory}!DocData.WalkResul |
| 2585 | 2605 | const cte_slot_index = self.comptime_exprs.items.len; |
| 2586 | 2606 | try self.comptime_exprs.append(self.arena, .{ |
| 2587 | 2607 | .code = msg, |
| 2588 | | .typeRef = .{ .type = @enumToInt(DocData.DocTypeKinds.ComptimeExpr) }, |
| 2589 | 2608 | }); |
| 2590 | | return DocData.WalkResult{ .comptimeExpr = cte_slot_index }; |
| 2609 | return DocData.WalkResult{ .expr = .{ .comptimeExpr = cte_slot_index } }; |
| 2591 | 2610 | } |