| ... | @@ -17,13 +17,14 @@ files: std.AutoHashMapUnmanaged(*File, usize) = .{}, | ... | @@ -17,13 +17,14 @@ files: std.AutoHashMapUnmanaged(*File, usize) = .{}, |
| 17 | calls: std.ArrayListUnmanaged(DocData.Call) = .{}, | 17 | calls: std.ArrayListUnmanaged(DocData.Call) = .{}, |
| 18 | types: std.ArrayListUnmanaged(DocData.Type) = .{}, | 18 | types: std.ArrayListUnmanaged(DocData.Type) = .{}, |
| 19 | decls: std.ArrayListUnmanaged(DocData.Decl) = .{}, | 19 | decls: std.ArrayListUnmanaged(DocData.Decl) = .{}, |
| | 20 | exprs: std.ArrayListUnmanaged(DocData.Expr) = .{}, |
| 20 | ast_nodes: std.ArrayListUnmanaged(DocData.AstNode) = .{}, | 21 | ast_nodes: std.ArrayListUnmanaged(DocData.AstNode) = .{}, |
| 21 | comptime_exprs: std.ArrayListUnmanaged(DocData.ComptimeExpr) = .{}, | 22 | comptime_exprs: std.ArrayListUnmanaged(DocData.ComptimeExpr) = .{}, |
| 22 | | 23 | |
| 23 | // These fields hold temporary state of the analysis process | 24 | // These fields hold temporary state of the analysis process |
| 24 | // and are mainly used by the decl path resolving algorithm. | 25 | // and are mainly used by the decl path resolving algorithm. |
| 25 | pending_ref_paths: std.AutoHashMapUnmanaged( | 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 | std.ArrayListUnmanaged(RefPathResumeInfo), | 28 | std.ArrayListUnmanaged(RefPathResumeInfo), |
| 28 | ) = .{}, | 29 | ) = .{}, |
| 29 | ref_paths_pending_on_decls: std.AutoHashMapUnmanaged( | 30 | ref_paths_pending_on_decls: std.AutoHashMapUnmanaged( |
| ... | @@ -37,7 +38,7 @@ ref_paths_pending_on_types: std.AutoHashMapUnmanaged( | ... | @@ -37,7 +38,7 @@ ref_paths_pending_on_types: std.AutoHashMapUnmanaged( |
| 37 | | 38 | |
| 38 | const RefPathResumeInfo = struct { | 39 | const RefPathResumeInfo = struct { |
| 39 | file: *File, | 40 | file: *File, |
| 40 | ref_path: []DocData.WalkResult, | 41 | ref_path: []DocData.Expr, |
| 41 | }; | 42 | }; |
| 42 | | 43 | |
| 43 | var arena_allocator: std.heap.ArenaAllocator = undefined; | 44 | var arena_allocator: std.heap.ArenaAllocator = undefined; |
| ... | @@ -80,7 +81,6 @@ pub fn generateZirData(self: *Autodoc) !void { | ... | @@ -80,7 +81,6 @@ pub fn generateZirData(self: *Autodoc) !void { |
| 80 | .ComptimeExpr = .{ .name = "ComptimeExpr" }, | 81 | .ComptimeExpr = .{ .name = "ComptimeExpr" }, |
| 81 | }); | 82 | }); |
| 82 | | 83 | |
| 83 | var tr = DocData.WalkResult{ .type = @enumToInt(Ref.usize_type) }; | | |
| 84 | // this skipts Ref.none but it's ok becuse we replaced it with ComptimeExpr | 84 | // this skipts Ref.none but it's ok becuse we replaced it with ComptimeExpr |
| 85 | var i: u32 = 1; | 85 | var i: u32 = 1; |
| 86 | while (i <= @enumToInt(Ref.anyerror_void_error_union_type)) : (i += 1) { | 86 | while (i <= @enumToInt(Ref.anyerror_void_error_union_type)) : (i += 1) { |
| ... | @@ -96,7 +96,6 @@ pub fn generateZirData(self: *Autodoc) !void { | ... | @@ -96,7 +96,6 @@ pub fn generateZirData(self: *Autodoc) !void { |
| 96 | .Array = .{ | 96 | .Array = .{ |
| 97 | .len = .{ | 97 | .len = .{ |
| 98 | .int = .{ | 98 | .int = .{ |
| 99 | .typeRef = &tr, | | |
| 100 | .value = 1, | 99 | .value = 1, |
| 101 | .negated = false, | 100 | .negated = false, |
| 102 | }, | 101 | }, |
| ... | @@ -163,7 +162,7 @@ pub fn generateZirData(self: *Autodoc) !void { | ... | @@ -163,7 +162,7 @@ pub fn generateZirData(self: *Autodoc) !void { |
| 163 | var root_scope = Scope{ .parent = null, .enclosing_type = main_type_index }; | 162 | var root_scope = Scope{ .parent = null, .enclosing_type = main_type_index }; |
| 164 | try self.ast_nodes.append(self.arena, .{ .name = "(root)" }); | 163 | try self.ast_nodes.append(self.arena, .{ .name = "(root)" }); |
| 165 | try self.files.put(self.arena, file, main_type_index); | 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 | if (self.ref_paths_pending_on_decls.count() > 0) { | 167 | if (self.ref_paths_pending_on_decls.count() > 0) { |
| 169 | @panic("some decl paths were never fully analized (pending on decls)"); | 168 | @panic("some decl paths were never fully analized (pending on decls)"); |
| ... | @@ -182,6 +181,7 @@ pub fn generateZirData(self: *Autodoc) !void { | ... | @@ -182,6 +181,7 @@ pub fn generateZirData(self: *Autodoc) !void { |
| 182 | .calls = self.calls.items, | 181 | .calls = self.calls.items, |
| 183 | .types = self.types.items, | 182 | .types = self.types.items, |
| 184 | .decls = self.decls.items, | 183 | .decls = self.decls.items, |
| | 184 | .exprs = self.exprs.items, |
| 185 | .astNodes = self.ast_nodes.items, | 185 | .astNodes = self.ast_nodes.items, |
| 186 | .comptimeExprs = self.comptime_exprs.items, | 186 | .comptimeExprs = self.comptime_exprs.items, |
| 187 | }; | 187 | }; |
| ... | @@ -305,11 +305,12 @@ const DocData = struct { | ... | @@ -305,11 +305,12 @@ const DocData = struct { |
| 305 | }, | 305 | }, |
| 306 | types: []Type, | 306 | types: []Type, |
| 307 | decls: []Decl, | 307 | decls: []Decl, |
| | 308 | exprs: []Expr, |
| 308 | comptimeExprs: []ComptimeExpr, | 309 | comptimeExprs: []ComptimeExpr, |
| 309 | const Call = struct { | 310 | const Call = struct { |
| 310 | func: WalkResult, | 311 | func: Expr, |
| 311 | args: []WalkResult, | 312 | args: []Expr, |
| 312 | ret: WalkResult, | 313 | ret: Expr, |
| 313 | }; | 314 | }; |
| 314 | | 315 | |
| 315 | /// All the type "families" as described by `std.builtin.TypeId` | 316 | /// All the type "families" as described by `std.builtin.TypeId` |
| ... | @@ -340,7 +341,6 @@ const DocData = struct { | ... | @@ -340,7 +341,6 @@ const DocData = struct { |
| 340 | | 341 | |
| 341 | const ComptimeExpr = struct { | 342 | const ComptimeExpr = struct { |
| 342 | code: []const u8, | 343 | code: []const u8, |
| 343 | typeRef: WalkResult, | | |
| 344 | }; | 344 | }; |
| 345 | const Package = struct { | 345 | const Package = struct { |
| 346 | name: []const u8 = "root", | 346 | name: []const u8 = "root", |
| ... | @@ -356,7 +356,6 @@ const DocData = struct { | ... | @@ -356,7 +356,6 @@ const DocData = struct { |
| 356 | kind: []const u8, | 356 | kind: []const u8, |
| 357 | isTest: bool, | 357 | isTest: bool, |
| 358 | src: usize, // index into astNodes | 358 | src: usize, // index into astNodes |
| 359 | // typeRef: TypeRef, | | |
| 360 | value: WalkResult, | 359 | value: WalkResult, |
| 361 | // The index in astNodes of the `test declname { }` node | 360 | // The index in astNodes of the `test declname { }` node |
| 362 | decltest: ?usize = null, | 361 | decltest: ?usize = null, |
| ... | @@ -383,18 +382,18 @@ const DocData = struct { | ... | @@ -383,18 +382,18 @@ const DocData = struct { |
| 383 | Float: struct { name: []const u8 }, | 382 | Float: struct { name: []const u8 }, |
| 384 | Pointer: struct { | 383 | Pointer: struct { |
| 385 | size: std.builtin.TypeInfo.Pointer.Size, | 384 | size: std.builtin.TypeInfo.Pointer.Size, |
| 386 | child: WalkResult, | 385 | child: Expr, |
| 387 | }, | 386 | }, |
| 388 | Array: struct { | 387 | Array: struct { |
| 389 | len: WalkResult, | 388 | len: Expr, |
| 390 | child: WalkResult, | 389 | child: Expr, |
| 391 | }, | 390 | }, |
| 392 | Struct: struct { | 391 | Struct: struct { |
| 393 | name: []const u8, | 392 | name: []const u8, |
| 394 | src: usize, // index into astNodes | 393 | src: usize, // index into astNodes |
| 395 | privDecls: []usize = &.{}, // index into decls | 394 | privDecls: []usize = &.{}, // index into decls |
| 396 | pubDecls: []usize = &.{}, // index into decls | 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 | ComptimeExpr: struct { name: []const u8 }, | 398 | ComptimeExpr: struct { name: []const u8 }, |
| 400 | ComptimeFloat: struct { name: []const u8 }, | 399 | ComptimeFloat: struct { name: []const u8 }, |
| ... | @@ -403,7 +402,7 @@ const DocData = struct { | ... | @@ -403,7 +402,7 @@ const DocData = struct { |
| 403 | Null: struct { name: []const u8 }, | 402 | Null: struct { name: []const u8 }, |
| 404 | Optional: struct { | 403 | Optional: struct { |
| 405 | name: []const u8, | 404 | name: []const u8, |
| 406 | child: WalkResult, | 405 | child: Expr, |
| 407 | }, | 406 | }, |
| 408 | ErrorUnion: struct { name: []const u8 }, | 407 | ErrorUnion: struct { name: []const u8 }, |
| 409 | ErrorSet: struct { | 408 | ErrorSet: struct { |
| ... | @@ -423,13 +422,13 @@ const DocData = struct { | ... | @@ -423,13 +422,13 @@ const DocData = struct { |
| 423 | src: usize, // index into astNodes | 422 | src: usize, // index into astNodes |
| 424 | privDecls: []usize = &.{}, // index into decls | 423 | privDecls: []usize = &.{}, // index into decls |
| 425 | pubDecls: []usize = &.{}, // index into decls | 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 | Fn: struct { | 427 | Fn: struct { |
| 429 | name: []const u8, | 428 | name: []const u8, |
| 430 | src: ?usize = null, // index into astNodes | 429 | src: ?usize = null, // index into astNodes |
| 431 | ret: WalkResult, | 430 | ret: Expr, |
| 432 | params: ?[]WalkResult = null, // (use src->fields to find names) | 431 | params: ?[]Expr = null, // (use src->fields to find names) |
| 433 | }, | 432 | }, |
| 434 | BoundFn: struct { name: []const u8 }, | 433 | BoundFn: struct { name: []const u8 }, |
| 435 | Opaque: struct { name: []const u8 }, | 434 | Opaque: struct { name: []const u8 }, |
| ... | @@ -517,75 +516,61 @@ const DocData = struct { | ... | @@ -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 | 519 | /// An Expr represents the (untyped) result of analizing instructions. |
| 521 | /// declaration. This includes: decls, fields, etc. | 520 | /// The data is normalized, which means that an Expr that results in a |
| 522 | /// | 521 | /// type definition will hold an index into `self.types`. |
| 523 | /// The data in WalkResult is mostly normalized, which means that a | 522 | pub const Expr = union(enum) { |
| 524 | /// WalkResult that results in a type definition will hold an index into | | |
| 525 | /// `self.types`. | | |
| 526 | const WalkResult = union(enum) { | | |
| 527 | comptimeExpr: usize, // index in `comptimeExprs` | 523 | comptimeExpr: usize, // index in `comptimeExprs` |
| 528 | void, | 524 | void, |
| 529 | @"unreachable", | 525 | @"unreachable", |
| 530 | @"null": *WalkResult, | 526 | @"null", |
| 531 | @"undefined": *WalkResult, | 527 | @"undefined", |
| 532 | @"struct": Struct, | 528 | @"struct": []FieldVal, |
| 533 | bool: bool, | 529 | bool: bool, |
| 534 | @"anytype", | 530 | @"anytype", |
| 535 | type: usize, // index in `types` | 531 | type: usize, // index in `types` |
| 536 | this: usize, // index in `types` | 532 | this: usize, // index in `types` |
| 537 | declRef: usize, // index in `decls` | 533 | declRef: usize, // index in `decls` |
| 538 | fieldRef: FieldRef, | 534 | fieldRef: FieldRef, |
| 539 | refPath: []WalkResult, | 535 | refPath: []Expr, |
| 540 | int: struct { | 536 | int: struct { |
| 541 | typeRef: *WalkResult, | | |
| 542 | value: usize, // direct value | 537 | value: usize, // direct value |
| 543 | negated: bool = false, | 538 | negated: bool = false, |
| 544 | }, | 539 | }, |
| 545 | float: struct { | 540 | float: f64, // direct value |
| 546 | typeRef: *WalkResult, | 541 | array: []usize, // index in `exprs` |
| 547 | value: f64, // direct value | | |
| 548 | negated: bool = false, | | |
| 549 | }, | | |
| 550 | array: Array, | | |
| 551 | call: usize, // index in `calls` | 542 | call: usize, // index in `calls` |
| 552 | enumLiteral: []const u8, | 543 | enumLiteral: []const u8, // direct value |
| 553 | typeOf: *WalkResult, | 544 | typeOf: usize, // index in `exprs` |
| 554 | sizeOf: *WalkResult, | 545 | as: struct { |
| | 546 | typeRefArg: ?usize, // index in `exprs` |
| | 547 | exprArg: usize, // index in `exprs` |
| | 548 | }, |
| | 549 | sizeOf: usize, // index in `exprs` |
| 555 | compileError: []const u8, | 550 | compileError: []const u8, |
| 556 | string: []const u8, | 551 | string: []const u8, // direct value |
| 557 | | | |
| 558 | const FieldRef = struct { | 552 | const FieldRef = struct { |
| 559 | type: usize, // index in `types` | 553 | type: usize, // index in `types` |
| 560 | index: usize, // index in type.fields | 554 | index: usize, // index in type.fields |
| 561 | }; | 555 | }; |
| 562 | | 556 | |
| 563 | const Struct = struct { | 557 | const FieldVal = struct { |
| 564 | typeRef: *WalkResult, | 558 | name: []const u8, |
| 565 | fieldVals: []FieldVal, | 559 | val: WalkResult, |
| 566 | | | |
| 567 | const FieldVal = struct { | | |
| 568 | name: []const u8, | | |
| 569 | val: WalkResult, | | |
| 570 | }; | | |
| 571 | }; | | |
| 572 | const Array = struct { | | |
| 573 | typeRef: *WalkResult, | | |
| 574 | data: []WalkResult, | | |
| 575 | }; | 560 | }; |
| 576 | | 561 | |
| 577 | pub fn jsonStringify( | 562 | pub fn jsonStringify( |
| 578 | self: WalkResult, | 563 | self: Expr, |
| 579 | options: std.json.StringifyOptions, | 564 | options: std.json.StringifyOptions, |
| 580 | w: anytype, | 565 | w: anytype, |
| 581 | ) std.os.WriteError!void { | 566 | ) std.os.WriteError!void { |
| 582 | switch (self) { | 567 | switch (self) { |
| 583 | .void, .@"unreachable", .@"anytype" => { | 568 | .void, .@"unreachable", .@"anytype", .@"null", .@"undefined" => { |
| 584 | try w.print( | 569 | try w.print( |
| 585 | \\{{ "{s}":{{}} }} | 570 | \\{{ "{s}":{{}} }} |
| 586 | , .{@tagName(self)}); | 571 | , .{@tagName(self)}); |
| 587 | }, | 572 | }, |
| 588 | .type, .comptimeExpr, .call, .this, .declRef => |v| { | 573 | .type, .comptimeExpr, .call, .this, .declRef, .typeOf => |v| { |
| 589 | try w.print( | 574 | try w.print( |
| 590 | \\{{ "{s}":{} }} | 575 | \\{{ "{s}":{} }} |
| 591 | , .{ @tagName(self), v }); | 576 | , .{ @tagName(self), v }); |
| ... | @@ -593,43 +578,28 @@ const DocData = struct { | ... | @@ -593,43 +578,28 @@ const DocData = struct { |
| 593 | .int => |v| { | 578 | .int => |v| { |
| 594 | const neg = if (v.negated) "-" else ""; | 579 | const neg = if (v.negated) "-" else ""; |
| 595 | try w.print( | 580 | try w.print( |
| 596 | \\{{ "int": {{ "typeRef": | 581 | \\{{ "int": {s}{} }} |
| 597 | , .{}); | | |
| 598 | try v.typeRef.jsonStringify(options, w); | | |
| 599 | try w.print( | | |
| 600 | \\, "value": {s}{} }} }} | | |
| 601 | , .{ neg, v.value }); | 582 | , .{ neg, v.value }); |
| 602 | }, | 583 | }, |
| 603 | .float => |v| { | 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 | try w.print( | 585 | try w.print( |
| 610 | \\, "value": {s}1 }} }} | 586 | \\{{ "float": {} }} |
| 611 | , .{neg}); | 587 | , .{v}); |
| 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 }); | | |
| 617 | }, | 588 | }, |
| 618 | .bool => |v| { | 589 | .bool => |v| { |
| 619 | try w.print( | 590 | try w.print( |
| 620 | \\{{ "bool":{} }} | 591 | \\{{ "bool":{} }} |
| 621 | , .{v}); | 592 | , .{v}); |
| 622 | }, | 593 | }, |
| 623 | .@"undefined" => |v| try std.json.stringify(v, options, w), | 594 | .sizeOf => |v| try std.json.stringify(v, options, w), |
| 624 | .@"null" => |v| try std.json.stringify(v, options, w), | 595 | .as => |v| try std.json.stringify(v, options, w), |
| 625 | .typeOf, .sizeOf => |v| try std.json.stringify(v, options, w), | | |
| 626 | .fieldRef => |v| try std.json.stringify( | 596 | .fieldRef => |v| try std.json.stringify( |
| 627 | struct { fieldRef: FieldRef }{ .fieldRef = v }, | 597 | struct { fieldRef: FieldRef }{ .fieldRef = v }, |
| 628 | options, | 598 | options, |
| 629 | w, | 599 | w, |
| 630 | ), | 600 | ), |
| 631 | .@"struct" => |v| try std.json.stringify( | 601 | .@"struct" => |v| try std.json.stringify( |
| 632 | struct { @"struct": Struct }{ .@"struct" = v }, | 602 | struct { @"struct": []FieldVal }{ .@"struct" = v }, |
| 633 | options, | 603 | options, |
| 634 | w, | 604 | w, |
| 635 | ), | 605 | ), |
| ... | @@ -642,7 +612,7 @@ const DocData = struct { | ... | @@ -642,7 +612,7 @@ const DocData = struct { |
| 642 | } | 612 | } |
| 643 | }, | 613 | }, |
| 644 | .array => |v| try std.json.stringify( | 614 | .array => |v| try std.json.stringify( |
| 645 | struct { @"array": Array }{ .@"array" = v }, | 615 | struct { @"array": []usize }{ .@"array" = v }, |
| 646 | options, | 616 | options, |
| 647 | w, | 617 | w, |
| 648 | ), | 618 | ), |
| ... | @@ -677,6 +647,17 @@ const DocData = struct { | ... | @@ -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 | /// Called when we need to analyze a Zir instruction. | 663 | /// Called when we need to analyze a Zir instruction. |
| ... | @@ -692,6 +673,7 @@ fn walkInstruction( | ... | @@ -692,6 +673,7 @@ fn walkInstruction( |
| 692 | file: *File, | 673 | file: *File, |
| 693 | parent_scope: *Scope, | 674 | parent_scope: *Scope, |
| 694 | inst_index: usize, | 675 | inst_index: usize, |
| | 676 | need_type: bool, // true if the caller needs us to provide also a typeRef |
| 695 | ) error{OutOfMemory}!DocData.WalkResult { | 677 | ) error{OutOfMemory}!DocData.WalkResult { |
| 696 | const tags = file.zir.instructions.items(.tag); | 678 | const tags = file.zir.instructions.items(.tag); |
| 697 | const data = file.zir.instructions.items(.data); | 679 | const data = file.zir.instructions.items(.data); |
| ... | @@ -711,11 +693,11 @@ fn walkInstruction( | ... | @@ -711,11 +693,11 @@ fn walkInstruction( |
| 711 | }, | 693 | }, |
| 712 | .closure_get => { | 694 | .closure_get => { |
| 713 | const inst_node = data[inst_index].inst_node; | 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 | .closure_capture => { | 698 | .closure_capture => { |
| 717 | const un_tok = data[inst_index].un_tok; | 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 | .import => { | 702 | .import => { |
| 721 | const str_tok = data[inst_index].str_tok; | 703 | const str_tok = data[inst_index].str_tok; |
| ... | @@ -726,17 +708,20 @@ fn walkInstruction( | ... | @@ -726,17 +708,20 @@ fn walkInstruction( |
| 726 | const cte_slot_index = self.comptime_exprs.items.len; | 708 | const cte_slot_index = self.comptime_exprs.items.len; |
| 727 | try self.comptime_exprs.append(self.arena, .{ | 709 | try self.comptime_exprs.append(self.arena, .{ |
| 728 | .code = path, | 710 | .code = path, |
| 729 | .typeRef = .{ .type = @enumToInt(DocData.DocTypeKinds.Type) }, | | |
| 730 | }); | 711 | }); |
| 731 | return DocData.WalkResult{ | 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 | const new_file = self.module.importFile(file, path) catch unreachable; | 718 | const new_file = self.module.importFile(file, path) catch unreachable; |
| 737 | const result = try self.files.getOrPut(self.arena, new_file.file); | 719 | const result = try self.files.getOrPut(self.arena, new_file.file); |
| 738 | if (result.found_existing) { | 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 | result.value_ptr.* = self.types.items.len; | 727 | result.value_ptr.* = self.types.items.len; |
| ... | @@ -745,18 +730,38 @@ fn walkInstruction( | ... | @@ -745,18 +730,38 @@ fn walkInstruction( |
| 745 | .parent = null, | 730 | .parent = null, |
| 746 | .enclosing_type = self.types.items.len, | 731 | .enclosing_type = self.types.items.len, |
| 747 | }; | 732 | }; |
| 748 | const new_file_walk_result = self.walkInstruction( | 733 | |
| | 734 | return self.walkInstruction( |
| 749 | new_file.file, | 735 | new_file.file, |
| 750 | &new_scope, | 736 | &new_scope, |
| 751 | Zir.main_struct_inst, | 737 | Zir.main_struct_inst, |
| | 738 | need_type, |
| 752 | ); | 739 | ); |
| 753 | | | |
| 754 | return new_file_walk_result; | | |
| 755 | }, | 740 | }, |
| 756 | .str => { | 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 | return DocData.WalkResult{ | 762 | return DocData.WalkResult{ |
| 759 | .string = str.get(file.zir), | 763 | .typeRef = tRef, |
| | 764 | .expr = .{ .string = str }, |
| 760 | }; | 765 | }; |
| 761 | }, | 766 | }, |
| 762 | .compile_error => { | 767 | .compile_error => { |
| ... | @@ -765,24 +770,23 @@ fn walkInstruction( | ... | @@ -765,24 +770,23 @@ fn walkInstruction( |
| 765 | file, | 770 | file, |
| 766 | parent_scope, | 771 | parent_scope, |
| 767 | un_node.operand, | 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 | .enum_literal => { | 780 | .enum_literal => { |
| 773 | const str_tok = data[inst_index].str_tok; | 781 | const str_tok = data[inst_index].str_tok; |
| 774 | const literal = file.zir.nullTerminatedString(str_tok.start); | 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 | .int => { | 785 | .int => { |
| 778 | const int = data[inst_index].int; | 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 | return DocData.WalkResult{ | 787 | return DocData.WalkResult{ |
| 782 | .int = .{ | 788 | .typeRef = .{ .type = @enumToInt(Ref.comptime_int_type) }, |
| 783 | .typeRef = t, | 789 | .expr = .{ .int = .{ .value = int } }, |
| 784 | .value = int, | | |
| 785 | }, | | |
| 786 | }; | 790 | }; |
| 787 | }, | 791 | }, |
| 788 | .error_union_type => { | 792 | .error_union_type => { |
| ... | @@ -790,20 +794,23 @@ fn walkInstruction( | ... | @@ -790,20 +794,23 @@ fn walkInstruction( |
| 790 | const extra = file.zir.extraData(Zir.Inst.Bin, pl_node.payload_index); | 794 | const extra = file.zir.extraData(Zir.Inst.Bin, pl_node.payload_index); |
| 791 | | 795 | |
| 792 | // TODO: return the actual error union instread of cheating | 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 | .ptr_type_simple => { | 799 | .ptr_type_simple => { |
| 796 | const ptr = data[inst_index].ptr_type_simple; | 800 | const ptr = data[inst_index].ptr_type_simple; |
| 797 | const type_slot_index = self.types.items.len; | 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 | try self.types.append(self.arena, .{ | 803 | try self.types.append(self.arena, .{ |
| 800 | .Pointer = .{ | 804 | .Pointer = .{ |
| 801 | .size = ptr.size, | 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 | .ptr_type => { | 815 | .ptr_type => { |
| 809 | const ptr = data[inst_index].ptr_type; | 816 | const ptr = data[inst_index].ptr_type; |
| ... | @@ -814,74 +821,84 @@ fn walkInstruction( | ... | @@ -814,74 +821,84 @@ fn walkInstruction( |
| 814 | file, | 821 | file, |
| 815 | parent_scope, | 822 | parent_scope, |
| 816 | extra.data.elem_type, | 823 | extra.data.elem_type, |
| | 824 | false, |
| 817 | ); | 825 | ); |
| 818 | try self.types.append(self.arena, .{ | 826 | try self.types.append(self.arena, .{ |
| 819 | .Pointer = .{ | 827 | .Pointer = .{ |
| 820 | .size = ptr.size, | 828 | .size = ptr.size, |
| 821 | .child = elem_type_ref, | 829 | .child = elem_type_ref.expr, |
| 822 | }, | 830 | }, |
| 823 | }); | 831 | }); |
| 824 | | 832 | return DocData.WalkResult{ |
| 825 | return DocData.WalkResult{ .type = type_slot_index }; | 833 | .typeRef = .{ .type = @enumToInt(Ref.type_type) }, |
| | 834 | .expr = .{ .type = type_slot_index }, |
| | 835 | }; |
| 826 | }, | 836 | }, |
| 827 | .array_type => { | 837 | .array_type => { |
| 828 | const bin = data[inst_index].bin; | 838 | const bin = data[inst_index].bin; |
| 829 | const len = try self.walkRef(file, parent_scope, bin.lhs); | 839 | const len = try self.walkRef(file, parent_scope, bin.lhs, false); |
| 830 | const child = try self.walkRef(file, parent_scope, bin.rhs); | 840 | const child = try self.walkRef(file, parent_scope, bin.rhs, false); |
| 831 | | 841 | |
| 832 | const type_slot_index = self.types.items.len; | 842 | const type_slot_index = self.types.items.len; |
| 833 | try self.types.append(self.arena, .{ | 843 | try self.types.append(self.arena, .{ |
| 834 | .Array = .{ | 844 | .Array = .{ |
| 835 | .len = len, | 845 | .len = len.expr, |
| 836 | .child = child, | 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 | .array_init => { | 854 | .array_init => { |
| 842 | const pl_node = data[inst_index].pl_node; | 855 | const pl_node = data[inst_index].pl_node; |
| 843 | const extra = file.zir.extraData(Zir.Inst.MultiOp, pl_node.payload_index); | 856 | const extra = file.zir.extraData(Zir.Inst.MultiOp, pl_node.payload_index); |
| 844 | const operands = file.zir.refSlice(extra.end, extra.data.operands_len); | 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 | for (operands) |op, idx| { | 864 | for (operands) |op, idx| { |
| 847 | array_data[idx] = try self.walkRef(file, parent_scope, op); | 865 | // we only ask to figure out type info for the first element |
| 848 | } | 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); | 873 | // We know that Zir wraps every operand in an @as expression |
| 851 | at.* = .{ .type = @enumToInt(Ref.usize_type) }; | 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 | const type_slot_index = self.types.items.len; | 879 | const type_slot_index = self.types.items.len; |
| 854 | try self.types.append(self.arena, .{ | 880 | try self.types.append(self.arena, .{ |
| 855 | .Array = .{ | 881 | .Array = .{ |
| 856 | .len = .{ | 882 | .len = .{ |
| 857 | .int = .{ | 883 | .int = .{ |
| 858 | .typeRef = at, | | |
| 859 | .value = operands.len, | 884 | .value = operands.len, |
| 860 | .negated = false, | 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); | 892 | return DocData.WalkResult{ |
| 868 | t.* = .{ .type = type_slot_index }; | 893 | .typeRef = .{ .type = type_slot_index }, |
| 869 | return DocData.WalkResult{ .array = .{ | 894 | .expr = .{ .array = array_data }, |
| 870 | .typeRef = t, | 895 | }; |
| 871 | .data = array_data, | | |
| 872 | } }; | | |
| 873 | }, | 896 | }, |
| 874 | .float => { | 897 | .float => { |
| 875 | const float = data[inst_index].float; | 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 | return DocData.WalkResult{ | 899 | return DocData.WalkResult{ |
| 881 | .float = .{ | 900 | .typeRef = .{ .type = @enumToInt(Ref.comptime_float_type) }, |
| 882 | .typeRef = t, | 901 | .expr = .{ .float = float }, |
| 883 | .value = float, | | |
| 884 | }, | | |
| 885 | }; | 902 | }; |
| 886 | }, | 903 | }, |
| 887 | .negate => { | 904 | .negate => { |
| ... | @@ -890,8 +907,9 @@ fn walkInstruction( | ... | @@ -890,8 +907,9 @@ fn walkInstruction( |
| 890 | file, | 907 | file, |
| 891 | parent_scope, | 908 | parent_scope, |
| 892 | un_node.operand, | 909 | un_node.operand, |
| | 910 | need_type, |
| 893 | ); | 911 | ); |
| 894 | switch (operand) { | 912 | switch (operand.expr) { |
| 895 | .int => |*int| int.negated = true, | 913 | .int => |*int| int.negated = true, |
| 896 | else => { | 914 | else => { |
| 897 | printWithContext( | 915 | printWithContext( |
| ... | @@ -906,75 +924,93 @@ fn walkInstruction( | ... | @@ -906,75 +924,93 @@ fn walkInstruction( |
| 906 | }, | 924 | }, |
| 907 | .size_of => { | 925 | .size_of => { |
| 908 | const un_node = data[inst_index].un_node; | 926 | const un_node = data[inst_index].un_node; |
| 909 | var operand = try self.arena.create(DocData.WalkResult); | 927 | const operand = try self.walkRef( |
| 910 | operand.* = try self.walkRef( | | |
| 911 | file, | 928 | file, |
| 912 | parent_scope, | 929 | parent_scope, |
| 913 | un_node.operand, | 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 | .typeof => { | 941 | .typeof => { |
| 919 | const un_node = data[inst_index].un_node; | 942 | const un_node = data[inst_index].un_node; |
| 920 | var operand = try self.arena.create(DocData.WalkResult); | 943 | const operand = try self.walkRef( |
| 921 | operand.* = try self.walkRef( | | |
| 922 | file, | 944 | file, |
| 923 | parent_scope, | 945 | parent_scope, |
| 924 | un_node.operand, | 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 | .as_node => { | 957 | .as_node => { |
| 929 | const pl_node = data[inst_index].pl_node; | 958 | const pl_node = data[inst_index].pl_node; |
| 930 | const extra = file.zir.extraData(Zir.Inst.As, pl_node.payload_index); | 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); | 960 | const dest_type_walk = try self.walkRef( |
| 932 | const dest_type_ref = dest_type_walk; | 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) { | 976 | const dest_type_idx = self.exprs.items.len; |
| 937 | else => printWithContext( | 977 | try self.exprs.append(self.arena, dest_type_walk.expr); |
| 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 | } | | |
| 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 | .optional_type => { | 991 | .optional_type => { |
| 961 | const un_node = data[inst_index].un_node; | 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 | file, | 994 | file, |
| 964 | parent_scope, | 995 | parent_scope, |
| 965 | un_node.operand, | 996 | un_node.operand, |
| | 997 | false, |
| 966 | ); | 998 | ); |
| 967 | const type_ref = operand; | 999 | |
| 968 | const res = DocData.WalkResult{ .type = self.types.items.len }; | 1000 | const operand_idx = self.types.items.len; |
| 969 | try self.types.append(self.arena, .{ | 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 | .decl_val, .decl_ref => { | 1010 | .decl_val, .decl_ref => { |
| 975 | const str_tok = data[inst_index].str_tok; | 1011 | const str_tok = data[inst_index].str_tok; |
| 976 | const decls_slot_index = parent_scope.resolveDeclName(str_tok.start); | 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 | .field_val, .field_call_bind, .field_ptr, .field_type => { | 1015 | .field_val, .field_call_bind, .field_ptr, .field_type => { |
| 980 | // TODO: field type uses Zir.Inst.FieldType, it just happens to have the | 1016 | // TODO: field type uses Zir.Inst.FieldType, it just happens to have the |
| ... | @@ -982,7 +1018,7 @@ fn walkInstruction( | ... | @@ -982,7 +1018,7 @@ fn walkInstruction( |
| 982 | const pl_node = data[inst_index].pl_node; | 1018 | const pl_node = data[inst_index].pl_node; |
| 983 | const extra = file.zir.extraData(Zir.Inst.Field, pl_node.payload_index); | 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 | var lhs = @enumToInt(extra.data.lhs) - Ref.typed_value_map.len; // underflow = need to handle Refs | 1022 | var lhs = @enumToInt(extra.data.lhs) - Ref.typed_value_map.len; // underflow = need to handle Refs |
| 987 | | 1023 | |
| 988 | try path.append(self.arena, .{ | 1024 | try path.append(self.arena, .{ |
| ... | @@ -1006,12 +1042,13 @@ fn walkInstruction( | ... | @@ -1006,12 +1042,13 @@ fn walkInstruction( |
| 1006 | lhs = @enumToInt(lhs_extra.data.lhs) - Ref.typed_value_map.len; // underflow = need to handle Refs | 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); | 1045 | // TODO: double check that we really don't need type info here |
| 1010 | try path.append(self.arena, wr); | 1046 | const wr = try self.walkInstruction(file, parent_scope, lhs, false); |
| | 1047 | try path.append(self.arena, wr.expr); |
| 1011 | | 1048 | |
| 1012 | // This way the data in `path` has the same ordering that the ref | 1049 | // This way the data in `path` has the same ordering that the ref |
| 1013 | // path has in the text: most general component first. | 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 | // Righ now, every element of `path` is a string except its first | 1053 | // Righ now, every element of `path` is a string except its first |
| 1017 | // element (at index 0). We're now going to attempt to resolve each | 1054 | // element (at index 0). We're now going to attempt to resolve each |
| ... | @@ -1026,7 +1063,7 @@ fn walkInstruction( | ... | @@ -1026,7 +1063,7 @@ fn walkInstruction( |
| 1026 | // any value that depends on that will have to become a | 1063 | // any value that depends on that will have to become a |
| 1027 | // comptimeExpr. | 1064 | // comptimeExpr. |
| 1028 | try self.tryResolveRefPath(file, lhs, path.items); | 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 | .int_type => { | 1068 | .int_type => { |
| 1032 | const int_type = data[inst_index].int_type; | 1069 | const int_type = data[inst_index].int_type; |
| ... | @@ -1037,28 +1074,37 @@ fn walkInstruction( | ... | @@ -1037,28 +1074,37 @@ fn walkInstruction( |
| 1037 | try self.types.append(self.arena, .{ | 1074 | try self.types.append(self.arena, .{ |
| 1038 | .Int = .{ .name = name }, | 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 | .block => { | 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 | try self.comptime_exprs.append(self.arena, .{ | 1086 | try self.comptime_exprs.append(self.arena, .{ |
| 1045 | .code = "if(banana) 1 else 0", | 1087 | .code = "if(banana) 1 else 0", |
| 1046 | .typeRef = .{ .type = 0 }, | | |
| 1047 | }); | 1088 | }); |
| 1048 | return res; | 1089 | return res; |
| 1049 | }, | 1090 | }, |
| 1050 | .block_inline => { | 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 | .struct_init => { | 1099 | .struct_init => { |
| 1054 | const pl_node = data[inst_index].pl_node; | 1100 | const pl_node = data[inst_index].pl_node; |
| 1055 | const extra = file.zir.extraData(Zir.Inst.StructInit, pl_node.payload_index); | 1101 | const extra = file.zir.extraData(Zir.Inst.StructInit, pl_node.payload_index); |
| 1056 | const field_vals = try self.arena.alloc( | 1102 | const field_vals = try self.arena.alloc( |
| 1057 | DocData.WalkResult.Struct.FieldVal, | 1103 | DocData.Expr.FieldVal, |
| 1058 | extra.data.fields_len, | 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 | var idx = extra.end; | 1108 | var idx = extra.end; |
| 1063 | for (field_vals) |*fv| { | 1109 | for (field_vals) |*fv| { |
| 1064 | const init_extra = file.zir.extraData(Zir.Inst.StructInit.Item, idx); | 1110 | const init_extra = file.zir.extraData(Zir.Inst.StructInit.Item, idx); |
| ... | @@ -1079,19 +1125,25 @@ fn walkInstruction( | ... | @@ -1079,19 +1125,25 @@ fn walkInstruction( |
| 1079 | file, | 1125 | file, |
| 1080 | parent_scope, | 1126 | parent_scope, |
| 1081 | field_extra.data.container_type, | 1127 | field_extra.data.container_type, |
| | 1128 | false, |
| 1082 | ); | 1129 | ); |
| 1083 | type_ref.* = wr; | 1130 | type_ref = wr.expr; |
| 1084 | } | 1131 | } |
| 1085 | break :blk file.zir.nullTerminatedString(field_extra.data.name_start); | 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 | fv.* = .{ .name = field_name, .val = value }; | 1140 | fv.* = .{ .name = field_name, .val = value }; |
| 1089 | } | 1141 | } |
| 1090 | | 1142 | |
| 1091 | return DocData.WalkResult{ .@"struct" = .{ | 1143 | return DocData.WalkResult{ |
| 1092 | .typeRef = type_ref, | 1144 | .typeRef = type_ref, |
| 1093 | .fieldVals = field_vals, | 1145 | .expr = .{ .@"struct" = field_vals }, |
| 1094 | } }; | 1146 | }; |
| 1095 | }, | 1147 | }, |
| 1096 | .error_set_decl => { | 1148 | .error_set_decl => { |
| 1097 | const pl_node = data[inst_index].pl_node; | 1149 | const pl_node = data[inst_index].pl_node; |
| ... | @@ -1122,7 +1174,10 @@ fn walkInstruction( | ... | @@ -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 | .param_anytype => { | 1182 | .param_anytype => { |
| 1128 | // Analysis of anytype function params happens in `.func`. | 1183 | // Analysis of anytype function params happens in `.func`. |
| ... | @@ -1134,9 +1189,8 @@ fn walkInstruction( | ... | @@ -1134,9 +1189,8 @@ fn walkInstruction( |
| 1134 | const cte_slot_index = self.comptime_exprs.items.len; | 1189 | const cte_slot_index = self.comptime_exprs.items.len; |
| 1135 | try self.comptime_exprs.append(self.arena, .{ | 1190 | try self.comptime_exprs.append(self.arena, .{ |
| 1136 | .code = name, | 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 | .param, .param_comptime => { | 1195 | .param, .param_comptime => { |
| 1142 | // See .param_anytype for more information. | 1196 | // See .param_anytype for more information. |
| ... | @@ -1146,41 +1200,46 @@ fn walkInstruction( | ... | @@ -1146,41 +1200,46 @@ fn walkInstruction( |
| 1146 | const cte_slot_index = self.comptime_exprs.items.len; | 1200 | const cte_slot_index = self.comptime_exprs.items.len; |
| 1147 | try self.comptime_exprs.append(self.arena, .{ | 1201 | try self.comptime_exprs.append(self.arena, .{ |
| 1148 | .code = name, | 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 | .call => { | 1206 | .call => { |
| 1154 | const pl_node = data[inst_index].pl_node; | 1207 | const pl_node = data[inst_index].pl_node; |
| 1155 | const extra = file.zir.extraData(Zir.Inst.Call, pl_node.payload_index); | 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 | const args_len = extra.data.flags.args_len; | 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 | const arg_refs = file.zir.refSlice(extra.end, args_len); | 1214 | const arg_refs = file.zir.refSlice(extra.end, args_len); |
| 1162 | for (arg_refs) |ref, idx| { | 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 | const cte_slot_index = self.comptime_exprs.items.len; | 1224 | const cte_slot_index = self.comptime_exprs.items.len; |
| 1169 | try self.comptime_exprs.append(self.arena, .{ | 1225 | try self.comptime_exprs.append(self.arena, .{ |
| 1170 | .code = "func call", | 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 | const call_slot_index = self.calls.items.len; | 1229 | const call_slot_index = self.calls.items.len; |
| 1177 | try self.calls.append(self.arena, .{ | 1230 | try self.calls.append(self.arena, .{ |
| 1178 | .func = callee, | 1231 | .func = callee.expr, |
| 1179 | .args = args, | 1232 | .args = args, |
| 1180 | .ret = .{ .comptimeExpr = cte_slot_index }, | 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 | .func, .func_inferred => { | 1244 | .func, .func_inferred => { |
| 1186 | const type_slot_index = self.types.items.len; | 1245 | const type_slot_index = self.types.items.len; |
| ... | @@ -1208,42 +1267,13 @@ fn walkInstruction( | ... | @@ -1208,42 +1267,13 @@ fn walkInstruction( |
| 1208 | }, | 1267 | }, |
| 1209 | | 1268 | |
| 1210 | .opaque_decl => return self.cteTodo("opaque {...}"), | 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 | .variable => { | 1270 | .variable => { |
| 1239 | const small = @bitCast(Zir.Inst.ExtendedVar.Small, extended.small); | 1271 | const small = @bitCast(Zir.Inst.ExtendedVar.Small, extended.small); |
| 1240 | var extra_index: usize = extended.operand; | 1272 | var extra_index: usize = extended.operand; |
| 1241 | if (small.has_lib_name) extra_index += 1; | 1273 | if (small.has_lib_name) extra_index += 1; |
| 1242 | if (small.has_align) extra_index += 1; | 1274 | if (small.has_align) extra_index += 1; |
| 1243 | | 1275 | |
| 1244 | const value: DocData.WalkResult = | 1276 | const value: DocData.WalkResult = if (small.has_init) .{ .expr = .{ .void = {} } } else .{ .expr = .{ .void = {} } }; |
| 1245 | if (small.has_init) | | |
| 1246 | .{ .void = {} } else .{ .void = {} }; | | |
| 1247 | | 1277 | |
| 1248 | return value; | 1278 | return value; |
| 1249 | }, | 1279 | }, |
| ... | @@ -1322,10 +1352,9 @@ fn walkInstruction( | ... | @@ -1322,10 +1352,9 @@ fn walkInstruction( |
| 1322 | extra_index, | 1352 | extra_index, |
| 1323 | ); | 1353 | ); |
| 1324 | | 1354 | |
| 1325 | // const body = file.zir.extra[extra_index..][0..body_len]; | | |
| 1326 | extra_index += body_len; | 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 | self.arena, | 1358 | self.arena, |
| 1330 | fields_len, | 1359 | fields_len, |
| 1331 | ); | 1360 | ); |
| ... | @@ -1369,7 +1398,10 @@ fn walkInstruction( | ... | @@ -1369,7 +1398,10 @@ fn walkInstruction( |
| 1369 | // anyway, but maybe we should put it elsewhere. | 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 | .enum_decl => { | 1406 | .enum_decl => { |
| 1375 | const type_slot_index = self.types.items.len; | 1407 | const type_slot_index = self.types.items.len; |
| ... | @@ -1516,8 +1548,10 @@ fn walkInstruction( | ... | @@ -1516,8 +1548,10 @@ fn walkInstruction( |
| 1516 | // decl paths. not doing it now since it's arena-allocated | 1548 | // decl paths. not doing it now since it's arena-allocated |
| 1517 | // anyway, but maybe we should put it elsewhere. | 1549 | // anyway, but maybe we should put it elsewhere. |
| 1518 | } | 1550 | } |
| 1519 | | 1551 | return DocData.WalkResult{ |
| 1520 | return DocData.WalkResult{ .type = type_slot_index }; | 1552 | .typeRef = .{ .type = @enumToInt(Ref.type_type) }, |
| | 1553 | .expr = .{ .type = type_slot_index }, |
| | 1554 | }; |
| 1521 | }, | 1555 | }, |
| 1522 | .struct_decl => { | 1556 | .struct_decl => { |
| 1523 | const type_slot_index = self.types.items.len; | 1557 | const type_slot_index = self.types.items.len; |
| ... | @@ -1590,7 +1624,7 @@ fn walkInstruction( | ... | @@ -1590,7 +1624,7 @@ fn walkInstruction( |
| 1590 | // const body = file.zir.extra[extra_index..][0..body_len]; | 1624 | // const body = file.zir.extra[extra_index..][0..body_len]; |
| 1591 | extra_index += body_len; | 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 | var field_name_indexes: std.ArrayListUnmanaged(usize) = .{}; | 1628 | var field_name_indexes: std.ArrayListUnmanaged(usize) = .{}; |
| 1595 | try self.collectStructFieldInfo( | 1629 | try self.collectStructFieldInfo( |
| 1596 | file, | 1630 | file, |
| ... | @@ -1626,11 +1660,16 @@ fn walkInstruction( | ... | @@ -1626,11 +1660,16 @@ fn walkInstruction( |
| 1626 | // decl paths. not doing it now since it's arena-allocated | 1660 | // decl paths. not doing it now since it's arena-allocated |
| 1627 | // anyway, but maybe we should put it elsewhere. | 1661 | // anyway, but maybe we should put it elsewhere. |
| 1628 | } | 1662 | } |
| 1629 | | 1663 | return DocData.WalkResult{ |
| 1630 | return DocData.WalkResult{ .type = type_slot_index }; | 1664 | .typeRef = .{ .type = @enumToInt(Ref.type_type) }, |
| | 1665 | .expr = .{ .type = type_slot_index }, |
| | 1666 | }; |
| 1631 | }, | 1667 | }, |
| 1632 | .this => { | 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,7 +1832,7 @@ fn walkDecls( |
| 1793 | .name = "test", | 1832 | .name = "test", |
| 1794 | .isTest = true, | 1833 | .isTest = true, |
| 1795 | .src = ast_node_index, | 1834 | .src = ast_node_index, |
| 1796 | .value = .{ .type = 0 }, | 1835 | .value = .{ .expr = .{ .type = 0 } }, |
| 1797 | .kind = "const", | 1836 | .kind = "const", |
| 1798 | }; | 1837 | }; |
| 1799 | continue; | 1838 | continue; |
| ... | @@ -1827,9 +1866,9 @@ fn walkDecls( | ... | @@ -1827,9 +1866,9 @@ fn walkDecls( |
| 1827 | }; | 1866 | }; |
| 1828 | | 1867 | |
| 1829 | const walk_result = if (is_test) // TODO: decide if tests should show up at all | 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 | else | 1870 | else |
| 1832 | try self.walkInstruction(file, scope, value_index); | 1871 | try self.walkInstruction(file, scope, value_index, true); |
| 1833 | | 1872 | |
| 1834 | if (is_pub) { | 1873 | if (is_pub) { |
| 1835 | try decl_indexes.append(self.arena, decls_slot_index); | 1874 | try decl_indexes.append(self.arena, decls_slot_index); |
| ... | @@ -1857,7 +1896,7 @@ fn walkDecls( | ... | @@ -1857,7 +1896,7 @@ fn walkDecls( |
| 1857 | .name = name, | 1896 | .name = name, |
| 1858 | .isTest = is_test, | 1897 | .isTest = is_test, |
| 1859 | .src = ast_node_index, | 1898 | .src = ast_node_index, |
| 1860 | // .typeRef = decl_type_ref, | 1899 | //.typeRef = decl_type_ref, |
| 1861 | .value = walk_result, | 1900 | .value = walk_result, |
| 1862 | .kind = "const", // find where this information can be found | 1901 | .kind = "const", // find where this information can be found |
| 1863 | }; | 1902 | }; |
| ... | @@ -1906,7 +1945,7 @@ fn tryResolveRefPath( | ... | @@ -1906,7 +1945,7 @@ fn tryResolveRefPath( |
| 1906 | /// File from which the decl path originates. | 1945 | /// File from which the decl path originates. |
| 1907 | file: *File, | 1946 | file: *File, |
| 1908 | inst_index: usize, // used only for panicWithContext | 1947 | inst_index: usize, // used only for panicWithContext |
| 1909 | path: []DocData.WalkResult, | 1948 | path: []DocData.Expr, |
| 1910 | ) error{OutOfMemory}!void { | 1949 | ) error{OutOfMemory}!void { |
| 1911 | var i: usize = 0; | 1950 | var i: usize = 0; |
| 1912 | outer: while (i < path.len - 1) : (i += 1) { | 1951 | outer: while (i < path.len - 1) : (i += 1) { |
| ... | @@ -1922,7 +1961,7 @@ fn tryResolveRefPath( | ... | @@ -1922,7 +1961,7 @@ fn tryResolveRefPath( |
| 1922 | .declRef => |decl_index| { | 1961 | .declRef => |decl_index| { |
| 1923 | const decl = self.decls.items[decl_index]; | 1962 | const decl = self.decls.items[decl_index]; |
| 1924 | if (decl._analyzed) { | 1963 | if (decl._analyzed) { |
| 1925 | resolved_parent = decl.value; | 1964 | resolved_parent = decl.value.expr; |
| 1926 | continue; | 1965 | continue; |
| 1927 | } | 1966 | } |
| 1928 | | 1967 | |
| ... | @@ -2004,7 +2043,7 @@ fn tryResolveRefPath( | ... | @@ -2004,7 +2043,7 @@ fn tryResolveRefPath( |
| 2004 | "TODO: handle `{s}`in tryResolveRefPath\nInfo: {}", | 2043 | "TODO: handle `{s}`in tryResolveRefPath\nInfo: {}", |
| 2005 | .{ @tagName(resolved_parent), resolved_parent }, | 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 | continue :outer; | 2047 | continue :outer; |
| 2009 | }, | 2048 | }, |
| 2010 | .comptimeExpr, .call => { | 2049 | .comptimeExpr, .call => { |
| ... | @@ -2088,7 +2127,7 @@ fn tryResolveRefPath( | ... | @@ -2088,7 +2127,7 @@ fn tryResolveRefPath( |
| 2088 | .{child_string}, | 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 | continue :outer; | 2131 | continue :outer; |
| 2093 | }, | 2132 | }, |
| 2094 | .Union => |t_union| { | 2133 | .Union => |t_union| { |
| ... | @@ -2134,7 +2173,7 @@ fn tryResolveRefPath( | ... | @@ -2134,7 +2173,7 @@ fn tryResolveRefPath( |
| 2134 | "failed to match `{s}` in union", | 2173 | "failed to match `{s}` in union", |
| 2135 | .{child_string}, | 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 | continue :outer; | 2177 | continue :outer; |
| 2139 | }, | 2178 | }, |
| 2140 | | 2179 | |
| ... | @@ -2181,7 +2220,7 @@ fn tryResolveRefPath( | ... | @@ -2181,7 +2220,7 @@ fn tryResolveRefPath( |
| 2181 | "failed to match `{s}` in struct", | 2220 | "failed to match `{s}` in struct", |
| 2182 | .{child_string}, | 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 | continue :outer; | 2224 | continue :outer; |
| 2186 | }, | 2225 | }, |
| 2187 | }, | 2226 | }, |
| ... | @@ -2214,7 +2253,7 @@ fn analyzeFunction( | ... | @@ -2214,7 +2253,7 @@ fn analyzeFunction( |
| 2214 | const fn_info = file.zir.getFnInfo(@intCast(u32, inst_index)); | 2253 | const fn_info = file.zir.getFnInfo(@intCast(u32, inst_index)); |
| 2215 | | 2254 | |
| 2216 | try self.ast_nodes.ensureUnusedCapacity(self.arena, fn_info.total_params_len); | 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 | self.arena, | 2257 | self.arena, |
| 2219 | fn_info.total_params_len, | 2258 | fn_info.total_params_len, |
| 2220 | ); | 2259 | ); |
| ... | @@ -2246,7 +2285,7 @@ fn analyzeFunction( | ... | @@ -2246,7 +2285,7 @@ fn analyzeFunction( |
| 2246 | }); | 2285 | }); |
| 2247 | | 2286 | |
| 2248 | param_type_refs.appendAssumeCapacity( | 2287 | param_type_refs.appendAssumeCapacity( |
| 2249 | DocData.WalkResult{ .@"anytype" = {} }, | 2288 | DocData.Expr{ .@"anytype" = {} }, |
| 2250 | ); | 2289 | ); |
| 2251 | }, | 2290 | }, |
| 2252 | .param, .param_comptime => { | 2291 | .param, .param_comptime => { |
| ... | @@ -2267,9 +2306,9 @@ fn analyzeFunction( | ... | @@ -2267,9 +2306,9 @@ fn analyzeFunction( |
| 2267 | | 2306 | |
| 2268 | const break_index = file.zir.extra[extra.end..][extra.data.body_len - 1]; | 2307 | const break_index = file.zir.extra[extra.end..][extra.data.body_len - 1]; |
| 2269 | const break_operand = data[break_index].@"break".operand; | 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,7 +2317,7 @@ fn analyzeFunction( |
| 2278 | const ret_type_ref = blk: { | 2317 | const ret_type_ref = blk: { |
| 2279 | const last_instr_index = fn_info.ret_ty_body[fn_info.ret_ty_body.len - 1]; | 2318 | const last_instr_index = fn_info.ret_ty_body[fn_info.ret_ty_body.len - 1]; |
| 2280 | const break_operand = data[last_instr_index].@"break".operand; | 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 | break :blk wr; | 2321 | break :blk wr; |
| 2283 | }; | 2322 | }; |
| 2284 | | 2323 | |
| ... | @@ -2288,10 +2327,13 @@ fn analyzeFunction( | ... | @@ -2288,10 +2327,13 @@ fn analyzeFunction( |
| 2288 | .name = "todo_name func", | 2327 | .name = "todo_name func", |
| 2289 | .src = self_ast_node_index, | 2328 | .src = self_ast_node_index, |
| 2290 | .params = param_type_refs.items, | 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 | fn collectUnionFieldInfo( | 2339 | fn collectUnionFieldInfo( |
| ... | @@ -2299,7 +2341,7 @@ fn collectUnionFieldInfo( | ... | @@ -2299,7 +2341,7 @@ fn collectUnionFieldInfo( |
| 2299 | file: *File, | 2341 | file: *File, |
| 2300 | scope: *Scope, | 2342 | scope: *Scope, |
| 2301 | fields_len: usize, | 2343 | fields_len: usize, |
| 2302 | field_type_refs: *std.ArrayListUnmanaged(DocData.WalkResult), | 2344 | field_type_refs: *std.ArrayListUnmanaged(DocData.Expr), |
| 2303 | field_name_indexes: *std.ArrayListUnmanaged(usize), | 2345 | field_name_indexes: *std.ArrayListUnmanaged(usize), |
| 2304 | ei: usize, | 2346 | ei: usize, |
| 2305 | ) !void { | 2347 | ) !void { |
| ... | @@ -2344,8 +2386,8 @@ fn collectUnionFieldInfo( | ... | @@ -2344,8 +2386,8 @@ fn collectUnionFieldInfo( |
| 2344 | | 2386 | |
| 2345 | // type | 2387 | // type |
| 2346 | { | 2388 | { |
| 2347 | const walk_result = try self.walkRef(file, scope, field_type); | 2389 | const walk_result = try self.walkRef(file, scope, field_type, false); |
| 2348 | try field_type_refs.append(self.arena, walk_result); | 2390 | try field_type_refs.append(self.arena, walk_result.expr); |
| 2349 | } | 2391 | } |
| 2350 | | 2392 | |
| 2351 | // ast node | 2393 | // ast node |
| ... | @@ -2368,7 +2410,7 @@ fn collectStructFieldInfo( | ... | @@ -2368,7 +2410,7 @@ fn collectStructFieldInfo( |
| 2368 | file: *File, | 2410 | file: *File, |
| 2369 | scope: *Scope, | 2411 | scope: *Scope, |
| 2370 | fields_len: usize, | 2412 | fields_len: usize, |
| 2371 | field_type_refs: *std.ArrayListUnmanaged(DocData.WalkResult), | 2413 | field_type_refs: *std.ArrayListUnmanaged(DocData.Expr), |
| 2372 | field_name_indexes: *std.ArrayListUnmanaged(usize), | 2414 | field_name_indexes: *std.ArrayListUnmanaged(usize), |
| 2373 | ei: usize, | 2415 | ei: usize, |
| 2374 | ) !void { | 2416 | ) !void { |
| ... | @@ -2410,8 +2452,8 @@ fn collectStructFieldInfo( | ... | @@ -2410,8 +2452,8 @@ fn collectStructFieldInfo( |
| 2410 | | 2452 | |
| 2411 | // type | 2453 | // type |
| 2412 | { | 2454 | { |
| 2413 | const walk_result = try self.walkRef(file, scope, field_type); | 2455 | const walk_result = try self.walkRef(file, scope, field_type, false); |
| 2414 | try field_type_refs.append(self.arena, walk_result); | 2456 | try field_type_refs.append(self.arena, walk_result.expr); |
| 2415 | } | 2457 | } |
| 2416 | | 2458 | |
| 2417 | // ast node | 2459 | // ast node |
| ... | @@ -2436,13 +2478,17 @@ fn walkRef( | ... | @@ -2436,13 +2478,17 @@ fn walkRef( |
| 2436 | file: *File, | 2478 | file: *File, |
| 2437 | parent_scope: *Scope, | 2479 | parent_scope: *Scope, |
| 2438 | ref: Ref, | 2480 | ref: Ref, |
| | 2481 | need_type: bool, // true when the caller needs also a typeRef for the return value |
| 2439 | ) !DocData.WalkResult { | 2482 | ) !DocData.WalkResult { |
| 2440 | const enum_value = @enumToInt(ref); | 2483 | const enum_value = @enumToInt(ref); |
| 2441 | if (enum_value <= @enumToInt(Ref.anyerror_void_error_union_type)) { | 2484 | if (enum_value <= @enumToInt(Ref.anyerror_void_error_union_type)) { |
| 2442 | // We can just return a type that indexes into `types` with the | 2485 | // We can just return a type that indexes into `types` with the |
| 2443 | // enum value because in the beginning we pre-filled `types` with | 2486 | // enum value because in the beginning we pre-filled `types` with |
| 2444 | // the types that are listed in `Ref`. | 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 | } else if (enum_value < Ref.typed_value_map.len) { | 2492 | } else if (enum_value < Ref.typed_value_map.len) { |
| 2447 | switch (ref) { | 2493 | switch (ref) { |
| 2448 | else => { | 2494 | else => { |
| ... | @@ -2451,69 +2497,62 @@ fn walkRef( | ... | @@ -2451,69 +2497,62 @@ fn walkRef( |
| 2451 | }); | 2497 | }); |
| 2452 | }, | 2498 | }, |
| 2453 | .undef => { | 2499 | .undef => { |
| 2454 | var t = try self.arena.create(DocData.WalkResult); | 2500 | return DocData.WalkResult{ .expr = .@"undefined" }; |
| 2455 | t.* = .void; | | |
| 2456 | | | |
| 2457 | return DocData.WalkResult{ .@"undefined" = t }; | | |
| 2458 | }, | 2501 | }, |
| 2459 | .zero => { | 2502 | .zero => { |
| 2460 | var t = try self.arena.create(DocData.WalkResult); | 2503 | return DocData.WalkResult{ |
| 2461 | t.* = .{ .type = @enumToInt(Ref.comptime_int_type) }; | 2504 | .typeRef = .{ .type = @enumToInt(Ref.comptime_int_type) }, |
| 2462 | return DocData.WalkResult{ .int = .{ | 2505 | .expr = .{ .int = .{ .value = 0 } }, |
| 2463 | .typeRef = t, | 2506 | }; |
| 2464 | .value = 0, | | |
| 2465 | } }; | | |
| 2466 | }, | 2507 | }, |
| 2467 | .one => { | 2508 | .one => { |
| 2468 | var t = try self.arena.create(DocData.WalkResult); | 2509 | return DocData.WalkResult{ |
| 2469 | t.* = .{ .type = @enumToInt(Ref.comptime_int_type) }; | 2510 | .typeRef = .{ .type = @enumToInt(Ref.comptime_int_type) }, |
| 2470 | return DocData.WalkResult{ .int = .{ | 2511 | .expr = .{ .int = .{ .value = 1 } }, |
| 2471 | .typeRef = t, | 2512 | }; |
| 2472 | .value = 1, | | |
| 2473 | } }; | | |
| 2474 | }, | 2513 | }, |
| 2475 | | 2514 | |
| 2476 | .void_value => { | 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 | .unreachable_value => { | 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 | .null_value => { | 2527 | .null_value => { |
| 2483 | var t = try self.arena.create(DocData.WalkResult); | 2528 | return DocData.WalkResult{ .expr = .@"null" }; |
| 2484 | t.* = .void; | | |
| 2485 | return DocData.WalkResult{ .@"null" = t }; | | |
| 2486 | }, | 2529 | }, |
| 2487 | .bool_true => { | 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 | .bool_false => { | 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 | .empty_struct => { | 2542 | .empty_struct => { |
| 2494 | var t = try self.arena.create(DocData.WalkResult); | 2543 | return DocData.WalkResult{ .expr = .{ .@"struct" = &.{} } }; |
| 2495 | t.* = .void; | | |
| 2496 | | | |
| 2497 | return DocData.WalkResult{ .@"struct" = .{ | | |
| 2498 | .typeRef = t, | | |
| 2499 | .fieldVals = &.{}, | | |
| 2500 | } }; | | |
| 2501 | }, | 2544 | }, |
| 2502 | .zero_usize => { | 2545 | .zero_usize => { |
| 2503 | var t = try self.arena.create(DocData.WalkResult); | 2546 | return DocData.WalkResult{ |
| 2504 | t.* = .{ .type = @enumToInt(Ref.usize_type) }; | 2547 | .typeRef = .{ .type = @enumToInt(Ref.usize_type) }, |
| 2505 | return DocData.WalkResult{ .int = .{ | 2548 | .expr = .{ .int = .{ .value = 0 } }, |
| 2506 | .typeRef = t, | 2549 | }; |
| 2507 | .value = 0, | | |
| 2508 | } }; | | |
| 2509 | }, | 2550 | }, |
| 2510 | .one_usize => { | 2551 | .one_usize => { |
| 2511 | var t = try self.arena.create(DocData.WalkResult); | 2552 | return DocData.WalkResult{ |
| 2512 | t.* = .{ .type = @enumToInt(Ref.usize_type) }; | 2553 | .typeRef = .{ .type = @enumToInt(Ref.usize_type) }, |
| 2513 | return DocData.WalkResult{ .int = .{ | 2554 | .expr = .{ .int = .{ .value = 1 } }, |
| 2514 | .typeRef = t, | 2555 | }; |
| 2515 | .value = 1, | | |
| 2516 | } }; | | |
| 2517 | }, | 2556 | }, |
| 2518 | // TODO: dunno what to do with those | 2557 | // TODO: dunno what to do with those |
| 2519 | // .calling_convention_c => { | 2558 | // .calling_convention_c => { |
| ... | @@ -2537,29 +2576,10 @@ fn walkRef( | ... | @@ -2537,29 +2576,10 @@ fn walkRef( |
| 2537 | } | 2576 | } |
| 2538 | } else { | 2577 | } else { |
| 2539 | const zir_index = enum_value - Ref.typed_value_map.len; | 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 | fn getBlockInlineBreak(zir: Zir, inst_index: usize) Zir.Inst.Ref { | 2583 | fn getBlockInlineBreak(zir: Zir, inst_index: usize) Zir.Inst.Ref { |
| 2564 | const tags = zir.instructions.items(.tag); | 2584 | const tags = zir.instructions.items(.tag); |
| 2565 | const data = zir.instructions.items(.data); | 2585 | const data = zir.instructions.items(.data); |
| ... | @@ -2585,7 +2605,6 @@ fn cteTodo(self: *Autodoc, msg: []const u8) error{OutOfMemory}!DocData.WalkResul | ... | @@ -2585,7 +2605,6 @@ fn cteTodo(self: *Autodoc, msg: []const u8) error{OutOfMemory}!DocData.WalkResul |
| 2585 | const cte_slot_index = self.comptime_exprs.items.len; | 2605 | const cte_slot_index = self.comptime_exprs.items.len; |
| 2586 | try self.comptime_exprs.append(self.arena, .{ | 2606 | try self.comptime_exprs.append(self.arena, .{ |
| 2587 | .code = msg, | 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 | } |