| ... | @@ -26,6 +26,7 @@ const trace = @import("tracy.zig").trace; | ... | @@ -26,6 +26,7 @@ const trace = @import("tracy.zig").trace; |
| 26 | const AstGen = @import("AstGen.zig"); | 26 | const AstGen = @import("AstGen.zig"); |
| 27 | const Sema = @import("Sema.zig"); | 27 | const Sema = @import("Sema.zig"); |
| 28 | const target_util = @import("target.zig"); | 28 | const target_util = @import("target.zig"); |
| | 29 | const Cache = @import("Cache.zig"); |
| 29 | | 30 | |
| 30 | /// General-purpose allocator. Used for both temporary and long-term storage. | 31 | /// General-purpose allocator. Used for both temporary and long-term storage. |
| 31 | gpa: *Allocator, | 32 | gpa: *Allocator, |
| ... | @@ -35,8 +36,6 @@ comp: *Compilation, | ... | @@ -35,8 +36,6 @@ comp: *Compilation, |
| 35 | zig_cache_artifact_directory: Compilation.Directory, | 36 | zig_cache_artifact_directory: Compilation.Directory, |
| 36 | /// Pointer to externally managed resource. `null` if there is no zig file being compiled. | 37 | /// Pointer to externally managed resource. `null` if there is no zig file being compiled. |
| 37 | root_pkg: *Package, | 38 | root_pkg: *Package, |
| 38 | /// Module owns this resource. | | |
| 39 | root_scope: *Scope.File, | | |
| 40 | /// It's rare for a decl to be exported, so we save memory by having a sparse map of | 39 | /// It's rare for a decl to be exported, so we save memory by having a sparse map of |
| 41 | /// Decl pointers to details about them being exported. | 40 | /// Decl pointers to details about them being exported. |
| 42 | /// The Export memory is owned by the `export_owners` table; the slice itself is owned by this table. | 41 | /// The Export memory is owned by the `export_owners` table; the slice itself is owned by this table. |
| ... | @@ -52,6 +51,12 @@ symbol_exports: std.StringArrayHashMapUnmanaged(*Export) = .{}, | ... | @@ -52,6 +51,12 @@ symbol_exports: std.StringArrayHashMapUnmanaged(*Export) = .{}, |
| 52 | export_owners: std.AutoArrayHashMapUnmanaged(*Decl, []*Export) = .{}, | 51 | export_owners: std.AutoArrayHashMapUnmanaged(*Decl, []*Export) = .{}, |
| 53 | /// Maps fully qualified namespaced names to the Decl struct for them. | 52 | /// Maps fully qualified namespaced names to the Decl struct for them. |
| 54 | decl_table: std.ArrayHashMapUnmanaged(Scope.NameHash, *Decl, Scope.name_hash_hash, Scope.name_hash_eql, false) = .{}, | 53 | decl_table: std.ArrayHashMapUnmanaged(Scope.NameHash, *Decl, Scope.name_hash_hash, Scope.name_hash_eql, false) = .{}, |
| | 54 | /// The set of all the files in the Module. We keep track of this in order to iterate |
| | 55 | /// over it and check which source files have been modified on the file system when |
| | 56 | /// an update is requested, as well as to cache `@import` results. |
| | 57 | /// Keys are fully resolved file paths. This table owns the keys and values. |
| | 58 | import_table: std.StringArrayHashMapUnmanaged(*Scope.File) = .{}, |
| | 59 | |
| 55 | /// We optimize memory usage for a compilation with no compile errors by storing the | 60 | /// We optimize memory usage for a compilation with no compile errors by storing the |
| 56 | /// error messages and mapping outside of `Decl`. | 61 | /// error messages and mapping outside of `Decl`. |
| 57 | /// The ErrorMsg memory is owned by the decl, using Module's general purpose allocator. | 62 | /// The ErrorMsg memory is owned by the decl, using Module's general purpose allocator. |
| ... | @@ -85,9 +90,6 @@ global_error_set: std.StringHashMapUnmanaged(ErrorInt) = .{}, | ... | @@ -85,9 +90,6 @@ global_error_set: std.StringHashMapUnmanaged(ErrorInt) = .{}, |
| 85 | /// Corresponds with `global_error_set`. | 90 | /// Corresponds with `global_error_set`. |
| 86 | error_name_list: ArrayListUnmanaged([]const u8) = .{}, | 91 | error_name_list: ArrayListUnmanaged([]const u8) = .{}, |
| 87 | | 92 | |
| 88 | /// Keys are fully qualified paths | | |
| 89 | import_table: std.StringArrayHashMapUnmanaged(*Scope.File) = .{}, | | |
| 90 | | | |
| 91 | /// Incrementing integer used to compare against the corresponding Decl | 93 | /// Incrementing integer used to compare against the corresponding Decl |
| 92 | /// field to determine whether a Decl's status applies to an ongoing update, or a | 94 | /// field to determine whether a Decl's status applies to an ongoing update, or a |
| 93 | /// previous analysis. | 95 | /// previous analysis. |
| ... | @@ -147,15 +149,16 @@ pub const Decl = struct { | ... | @@ -147,15 +149,16 @@ pub const Decl = struct { |
| 147 | /// This is necessary for mapping them to an address in the output file. | 149 | /// This is necessary for mapping them to an address in the output file. |
| 148 | /// Memory owned by this decl, using Module's allocator. | 150 | /// Memory owned by this decl, using Module's allocator. |
| 149 | name: [*:0]const u8, | 151 | name: [*:0]const u8, |
| 150 | /// The direct parent container of the Decl. | 152 | /// The direct parent namespace of the Decl. |
| 151 | /// Reference to externally owned memory. | 153 | /// Reference to externally owned memory. |
| 152 | container: *Scope.Container, | 154 | /// This is `null` for the Decl that represents a `File`. |
| | 155 | namespace: *Scope.Namespace, |
| 153 | | 156 | |
| 154 | /// An integer that can be checked against the corresponding incrementing | 157 | /// An integer that can be checked against the corresponding incrementing |
| 155 | /// generation field of Module. This is used to determine whether `complete` status | 158 | /// generation field of Module. This is used to determine whether `complete` status |
| 156 | /// represents pre- or post- re-analysis. | 159 | /// represents pre- or post- re-analysis. |
| 157 | generation: u32, | 160 | generation: u32, |
| 158 | /// The AST Node index or ZIR Inst index that contains this declaration. | 161 | /// The AST node index of this declaration. |
| 159 | /// Must be recomputed when the corresponding source file is modified. | 162 | /// Must be recomputed when the corresponding source file is modified. |
| 160 | src_node: ast.Node.Index, | 163 | src_node: ast.Node.Index, |
| 161 | | 164 | |
| ... | @@ -273,22 +276,22 @@ pub const Decl = struct { | ... | @@ -273,22 +276,22 @@ pub const Decl = struct { |
| 273 | } | 276 | } |
| 274 | | 277 | |
| 275 | pub fn srcToken(decl: Decl) u32 { | 278 | pub fn srcToken(decl: Decl) u32 { |
| 276 | const tree = &decl.container.file_scope.tree; | 279 | const tree = &decl.namespace.file_scope.tree; |
| 277 | return tree.firstToken(decl.src_node); | 280 | return tree.firstToken(decl.src_node); |
| 278 | } | 281 | } |
| 279 | | 282 | |
| 280 | pub fn srcByteOffset(decl: Decl) u32 { | 283 | pub fn srcByteOffset(decl: Decl) u32 { |
| 281 | const tree = &decl.container.file_scope.tree; | 284 | const tree = &decl.namespace.file_scope.tree; |
| 282 | return tree.tokens.items(.start)[decl.srcToken()]; | 285 | return tree.tokens.items(.start)[decl.srcToken()]; |
| 283 | } | 286 | } |
| 284 | | 287 | |
| 285 | pub fn fullyQualifiedNameHash(decl: Decl) Scope.NameHash { | 288 | pub fn fullyQualifiedNameHash(decl: Decl) Scope.NameHash { |
| 286 | return decl.container.fullyQualifiedNameHash(mem.spanZ(decl.name)); | 289 | return decl.namespace.fullyQualifiedNameHash(mem.spanZ(decl.name)); |
| 287 | } | 290 | } |
| 288 | | 291 | |
| 289 | pub fn renderFullyQualifiedName(decl: Decl, writer: anytype) !void { | 292 | pub fn renderFullyQualifiedName(decl: Decl, writer: anytype) !void { |
| 290 | const unqualified_name = mem.spanZ(decl.name); | 293 | const unqualified_name = mem.spanZ(decl.name); |
| 291 | return decl.container.renderFullyQualifiedName(unqualified_name, writer); | 294 | return decl.namespace.renderFullyQualifiedName(unqualified_name, writer); |
| 292 | } | 295 | } |
| 293 | | 296 | |
| 294 | pub fn getFullyQualifiedName(decl: Decl, gpa: *Allocator) ![]u8 { | 297 | pub fn getFullyQualifiedName(decl: Decl, gpa: *Allocator) ![]u8 { |
| ... | @@ -330,7 +333,7 @@ pub const Decl = struct { | ... | @@ -330,7 +333,7 @@ pub const Decl = struct { |
| 330 | } | 333 | } |
| 331 | | 334 | |
| 332 | pub fn getFileScope(decl: Decl) *Scope.File { | 335 | pub fn getFileScope(decl: Decl) *Scope.File { |
| 333 | return decl.container.file_scope; | 336 | return decl.namespace.file_scope; |
| 334 | } | 337 | } |
| 335 | | 338 | |
| 336 | pub fn getEmitH(decl: *Decl, module: *Module) *EmitH { | 339 | pub fn getEmitH(decl: *Decl, module: *Module) *EmitH { |
| ... | @@ -377,7 +380,7 @@ pub const Struct = struct { | ... | @@ -377,7 +380,7 @@ pub const Struct = struct { |
| 377 | /// Set of field names in declaration order. | 380 | /// Set of field names in declaration order. |
| 378 | fields: std.StringArrayHashMapUnmanaged(Field), | 381 | fields: std.StringArrayHashMapUnmanaged(Field), |
| 379 | /// Represents the declarations inside this struct. | 382 | /// Represents the declarations inside this struct. |
| 380 | container: Scope.Container, | 383 | namespace: Scope.Namespace, |
| 381 | | 384 | |
| 382 | /// Offset from `owner_decl`, points to the struct AST node. | 385 | /// Offset from `owner_decl`, points to the struct AST node. |
| 383 | node_offset: i32, | 386 | node_offset: i32, |
| ... | @@ -434,7 +437,7 @@ pub const EnumFull = struct { | ... | @@ -434,7 +437,7 @@ pub const EnumFull = struct { |
| 434 | /// If this hash map is empty, it means the enum tags are auto-numbered. | 437 | /// If this hash map is empty, it means the enum tags are auto-numbered. |
| 435 | values: ValueMap, | 438 | values: ValueMap, |
| 436 | /// Represents the declarations inside this struct. | 439 | /// Represents the declarations inside this struct. |
| 437 | container: Scope.Container, | 440 | namespace: Scope.Namespace, |
| 438 | /// Offset from `owner_decl`, points to the enum decl AST node. | 441 | /// Offset from `owner_decl`, points to the enum decl AST node. |
| 439 | node_offset: i32, | 442 | node_offset: i32, |
| 440 | | 443 | |
| ... | @@ -521,7 +524,7 @@ pub const Scope = struct { | ... | @@ -521,7 +524,7 @@ pub const Scope = struct { |
| 521 | .local_val => return scope.cast(LocalVal).?.gen_zir.astgen.arena, | 524 | .local_val => return scope.cast(LocalVal).?.gen_zir.astgen.arena, |
| 522 | .local_ptr => return scope.cast(LocalPtr).?.gen_zir.astgen.arena, | 525 | .local_ptr => return scope.cast(LocalPtr).?.gen_zir.astgen.arena, |
| 523 | .file => unreachable, | 526 | .file => unreachable, |
| 524 | .container => unreachable, | 527 | .namespace => unreachable, |
| 525 | .decl_ref => unreachable, | 528 | .decl_ref => unreachable, |
| 526 | } | 529 | } |
| 527 | } | 530 | } |
| ... | @@ -533,7 +536,7 @@ pub const Scope = struct { | ... | @@ -533,7 +536,7 @@ pub const Scope = struct { |
| 533 | .local_val => scope.cast(LocalVal).?.gen_zir.astgen.decl, | 536 | .local_val => scope.cast(LocalVal).?.gen_zir.astgen.decl, |
| 534 | .local_ptr => scope.cast(LocalPtr).?.gen_zir.astgen.decl, | 537 | .local_ptr => scope.cast(LocalPtr).?.gen_zir.astgen.decl, |
| 535 | .file => null, | 538 | .file => null, |
| 536 | .container => null, | 539 | .namespace => null, |
| 537 | .decl_ref => scope.cast(DeclRef).?.decl, | 540 | .decl_ref => scope.cast(DeclRef).?.decl, |
| 538 | }; | 541 | }; |
| 539 | } | 542 | } |
| ... | @@ -545,36 +548,21 @@ pub const Scope = struct { | ... | @@ -545,36 +548,21 @@ pub const Scope = struct { |
| 545 | .local_val => scope.cast(LocalVal).?.gen_zir.astgen.decl, | 548 | .local_val => scope.cast(LocalVal).?.gen_zir.astgen.decl, |
| 546 | .local_ptr => scope.cast(LocalPtr).?.gen_zir.astgen.decl, | 549 | .local_ptr => scope.cast(LocalPtr).?.gen_zir.astgen.decl, |
| 547 | .file => null, | 550 | .file => null, |
| 548 | .container => null, | 551 | .namespace => null, |
| 549 | .decl_ref => scope.cast(DeclRef).?.decl, | 552 | .decl_ref => scope.cast(DeclRef).?.decl, |
| 550 | }; | 553 | }; |
| 551 | } | 554 | } |
| 552 | | 555 | |
| 553 | /// Asserts the scope has a parent which is a Container and returns it. | 556 | /// Asserts the scope has a parent which is a Namespace and returns it. |
| 554 | pub fn namespace(scope: *Scope) *Container { | 557 | pub fn namespace(scope: *Scope) *Namespace { |
| 555 | switch (scope.tag) { | 558 | switch (scope.tag) { |
| 556 | .block => return scope.cast(Block).?.sema.owner_decl.container, | 559 | .block => return scope.cast(Block).?.sema.owner_decl.namespace, |
| 557 | .gen_zir => return scope.cast(GenZir).?.astgen.decl.container, | 560 | .gen_zir => return scope.cast(GenZir).?.astgen.decl.namespace, |
| 558 | .local_val => return scope.cast(LocalVal).?.gen_zir.astgen.decl.container, | 561 | .local_val => return scope.cast(LocalVal).?.gen_zir.astgen.decl.namespace, |
| 559 | .local_ptr => return scope.cast(LocalPtr).?.gen_zir.astgen.decl.container, | 562 | .local_ptr => return scope.cast(LocalPtr).?.gen_zir.astgen.decl.namespace, |
| 560 | .file => return &scope.cast(File).?.root_container, | 563 | .file => return scope.cast(File).?.namespace, |
| 561 | .container => return scope.cast(Container).?, | 564 | .namespace => return scope.cast(Namespace).?, |
| 562 | .decl_ref => return scope.cast(DeclRef).?.decl.container, | 565 | .decl_ref => return scope.cast(DeclRef).?.decl.namespace, |
| 563 | } | | |
| 564 | } | | |
| 565 | | | |
| 566 | /// Must generate unique bytes with no collisions with other decls. | | |
| 567 | /// The point of hashing here is only to limit the number of bytes of | | |
| 568 | /// the unique identifier to a fixed size (16 bytes). | | |
| 569 | pub fn fullyQualifiedNameHash(scope: *Scope, name: []const u8) NameHash { | | |
| 570 | switch (scope.tag) { | | |
| 571 | .block => unreachable, | | |
| 572 | .gen_zir => unreachable, | | |
| 573 | .local_val => unreachable, | | |
| 574 | .local_ptr => unreachable, | | |
| 575 | .file => unreachable, | | |
| 576 | .container => return scope.cast(Container).?.fullyQualifiedNameHash(name), | | |
| 577 | .decl_ref => unreachable, | | |
| 578 | } | 566 | } |
| 579 | } | 567 | } |
| 580 | | 568 | |
| ... | @@ -582,12 +570,12 @@ pub const Scope = struct { | ... | @@ -582,12 +570,12 @@ pub const Scope = struct { |
| 582 | pub fn tree(scope: *Scope) *const ast.Tree { | 570 | pub fn tree(scope: *Scope) *const ast.Tree { |
| 583 | switch (scope.tag) { | 571 | switch (scope.tag) { |
| 584 | .file => return &scope.cast(File).?.tree, | 572 | .file => return &scope.cast(File).?.tree, |
| 585 | .block => return &scope.cast(Block).?.src_decl.container.file_scope.tree, | 573 | .block => return &scope.cast(Block).?.src_decl.namespace.file_scope.tree, |
| 586 | .gen_zir => return scope.cast(GenZir).?.tree(), | 574 | .gen_zir => return scope.cast(GenZir).?.tree(), |
| 587 | .local_val => return &scope.cast(LocalVal).?.gen_zir.astgen.decl.container.file_scope.tree, | 575 | .local_val => return &scope.cast(LocalVal).?.gen_zir.astgen.decl.namespace.file_scope.tree, |
| 588 | .local_ptr => return &scope.cast(LocalPtr).?.gen_zir.astgen.decl.container.file_scope.tree, | 576 | .local_ptr => return &scope.cast(LocalPtr).?.gen_zir.astgen.decl.namespace.file_scope.tree, |
| 589 | .container => return &scope.cast(Container).?.file_scope.tree, | 577 | .namespace => return &scope.cast(Namespace).?.file_scope.tree, |
| 590 | .decl_ref => return &scope.cast(DeclRef).?.decl.container.file_scope.tree, | 578 | .decl_ref => return &scope.cast(DeclRef).?.decl.namespace.file_scope.tree, |
| 591 | } | 579 | } |
| 592 | } | 580 | } |
| 593 | | 581 | |
| ... | @@ -599,16 +587,16 @@ pub const Scope = struct { | ... | @@ -599,16 +587,16 @@ pub const Scope = struct { |
| 599 | .local_val => return scope.cast(LocalVal).?.gen_zir, | 587 | .local_val => return scope.cast(LocalVal).?.gen_zir, |
| 600 | .local_ptr => return scope.cast(LocalPtr).?.gen_zir, | 588 | .local_ptr => return scope.cast(LocalPtr).?.gen_zir, |
| 601 | .file => unreachable, | 589 | .file => unreachable, |
| 602 | .container => unreachable, | 590 | .namespace => unreachable, |
| 603 | .decl_ref => unreachable, | 591 | .decl_ref => unreachable, |
| 604 | }; | 592 | }; |
| 605 | } | 593 | } |
| 606 | | 594 | |
| 607 | /// Asserts the scope has a parent which is a Container or File and | 595 | /// Asserts the scope has a parent which is a Namespace or File and |
| 608 | /// returns the sub_file_path field. | 596 | /// returns the sub_file_path field. |
| 609 | pub fn subFilePath(base: *Scope) []const u8 { | 597 | pub fn subFilePath(base: *Scope) []const u8 { |
| 610 | switch (base.tag) { | 598 | switch (base.tag) { |
| 611 | .container => return @fieldParentPtr(Container, "base", base).file_scope.sub_file_path, | 599 | .namespace => return @fieldParentPtr(Namespace, "base", base).file_scope.sub_file_path, |
| 612 | .file => return @fieldParentPtr(File, "base", base).sub_file_path, | 600 | .file => return @fieldParentPtr(File, "base", base).sub_file_path, |
| 613 | .block => unreachable, | 601 | .block => unreachable, |
| 614 | .gen_zir => unreachable, | 602 | .gen_zir => unreachable, |
| ... | @@ -618,30 +606,18 @@ pub const Scope = struct { | ... | @@ -618,30 +606,18 @@ pub const Scope = struct { |
| 618 | } | 606 | } |
| 619 | } | 607 | } |
| 620 | | 608 | |
| 621 | pub fn getSource(base: *Scope, module: *Module) ![:0]const u8 { | | |
| 622 | switch (base.tag) { | | |
| 623 | .container => return @fieldParentPtr(Container, "base", base).file_scope.getSource(module), | | |
| 624 | .file => return @fieldParentPtr(File, "base", base).getSource(module), | | |
| 625 | .gen_zir => unreachable, | | |
| 626 | .local_val => unreachable, | | |
| 627 | .local_ptr => unreachable, | | |
| 628 | .block => unreachable, | | |
| 629 | .decl_ref => unreachable, | | |
| 630 | } | | |
| 631 | } | | |
| 632 | | | |
| 633 | /// When called from inside a Block Scope, chases the src_decl, not the owner_decl. | 609 | /// When called from inside a Block Scope, chases the src_decl, not the owner_decl. |
| 634 | pub fn getFileScope(base: *Scope) *Scope.File { | 610 | pub fn getFileScope(base: *Scope) *Scope.File { |
| 635 | var cur = base; | 611 | var cur = base; |
| 636 | while (true) { | 612 | while (true) { |
| 637 | cur = switch (cur.tag) { | 613 | cur = switch (cur.tag) { |
| 638 | .container => return @fieldParentPtr(Container, "base", cur).file_scope, | 614 | .namespace => return @fieldParentPtr(Namespace, "base", cur).file_scope, |
| 639 | .file => return @fieldParentPtr(File, "base", cur), | 615 | .file => return @fieldParentPtr(File, "base", cur), |
| 640 | .gen_zir => @fieldParentPtr(GenZir, "base", cur).parent, | 616 | .gen_zir => @fieldParentPtr(GenZir, "base", cur).parent, |
| 641 | .local_val => @fieldParentPtr(LocalVal, "base", cur).parent, | 617 | .local_val => @fieldParentPtr(LocalVal, "base", cur).parent, |
| 642 | .local_ptr => @fieldParentPtr(LocalPtr, "base", cur).parent, | 618 | .local_ptr => @fieldParentPtr(LocalPtr, "base", cur).parent, |
| 643 | .block => return @fieldParentPtr(Block, "base", cur).src_decl.container.file_scope, | 619 | .block => return @fieldParentPtr(Block, "base", cur).src_decl.namespace.file_scope, |
| 644 | .decl_ref => return @fieldParentPtr(DeclRef, "base", cur).decl.container.file_scope, | 620 | .decl_ref => return @fieldParentPtr(DeclRef, "base", cur).decl.namespace.file_scope, |
| 645 | }; | 621 | }; |
| 646 | } | 622 | } |
| 647 | } | 623 | } |
| ... | @@ -657,8 +633,8 @@ pub const Scope = struct { | ... | @@ -657,8 +633,8 @@ pub const Scope = struct { |
| 657 | pub const Tag = enum { | 633 | pub const Tag = enum { |
| 658 | /// .zig source code. | 634 | /// .zig source code. |
| 659 | file, | 635 | file, |
| 660 | /// struct, enum or union, every .file contains one of these. | 636 | /// Namespace owned by structs, enums, unions, and opaques for decls. |
| 661 | container, | 637 | namespace, |
| 662 | block, | 638 | block, |
| 663 | gen_zir, | 639 | gen_zir, |
| 664 | local_val, | 640 | local_val, |
| ... | @@ -669,37 +645,44 @@ pub const Scope = struct { | ... | @@ -669,37 +645,44 @@ pub const Scope = struct { |
| 669 | decl_ref, | 645 | decl_ref, |
| 670 | }; | 646 | }; |
| 671 | | 647 | |
| 672 | pub const Container = struct { | 648 | /// The container that structs, enums, unions, and opaques have. |
| 673 | pub const base_tag: Tag = .container; | 649 | pub const Namespace = struct { |
| | 650 | pub const base_tag: Tag = .namespace; |
| 674 | base: Scope = Scope{ .tag = base_tag }, | 651 | base: Scope = Scope{ .tag = base_tag }, |
| 675 | | 652 | |
| | 653 | parent: ?*Namespace, |
| 676 | file_scope: *Scope.File, | 654 | file_scope: *Scope.File, |
| 677 | parent_name_hash: NameHash, | 655 | parent_name_hash: NameHash, |
| 678 | | 656 | /// Will be a struct, enum, union, or opaque. |
| 679 | /// Direct children of the file. | | |
| 680 | decls: std.AutoArrayHashMapUnmanaged(*Decl, void) = .{}, | | |
| 681 | ty: Type, | 657 | ty: Type, |
| | 658 | /// Direct children of the namespace. Used during an update to detect |
| | 659 | /// which decls have been added/removed from source. |
| | 660 | decls: std.AutoArrayHashMapUnmanaged(*Decl, void) = .{}, |
| 682 | | 661 | |
| 683 | pub fn deinit(cont: *Container, gpa: *Allocator) void { | 662 | pub fn deinit(ns: *Namespace, gpa: *Allocator) void { |
| 684 | cont.decls.deinit(gpa); | 663 | ns.decls.deinit(gpa); |
| 685 | // TODO either Container of File should have an arena for sub_file_path and ty | 664 | ns.* = undefined; |
| 686 | gpa.destroy(cont.ty.castTag(.empty_struct).?); | | |
| 687 | gpa.free(cont.file_scope.sub_file_path); | | |
| 688 | cont.* = undefined; | | |
| 689 | } | 665 | } |
| 690 | | 666 | |
| 691 | pub fn removeDecl(cont: *Container, child: *Decl) void { | 667 | pub fn removeDecl(ns: *Namespace, child: *Decl) void { |
| 692 | _ = cont.decls.swapRemove(child); | 668 | _ = ns.decls.swapRemove(child); |
| 693 | } | 669 | } |
| 694 | | 670 | |
| 695 | pub fn fullyQualifiedNameHash(cont: *Container, name: []const u8) NameHash { | 671 | /// Must generate unique bytes with no collisions with other decls. |
| 696 | return std.zig.hashName(cont.parent_name_hash, ".", name); | 672 | /// The point of hashing here is only to limit the number of bytes of |
| | 673 | /// the unique identifier to a fixed size (16 bytes). |
| | 674 | pub fn fullyQualifiedNameHash(ns: Namespace, name: []const u8) NameHash { |
| | 675 | return std.zig.hashName(ns.parent_name_hash, ".", name); |
| 697 | } | 676 | } |
| 698 | | 677 | |
| 699 | pub fn renderFullyQualifiedName(cont: Container, name: []const u8, writer: anytype) !void { | 678 | pub fn renderFullyQualifiedName(ns: Namespace, name: []const u8, writer: anytype) !void { |
| 700 | // TODO this should render e.g. "std.fs.Dir.OpenOptions" | 679 | // TODO this should render e.g. "std.fs.Dir.OpenOptions" |
| 701 | return writer.writeAll(name); | 680 | return writer.writeAll(name); |
| 702 | } | 681 | } |
| | 682 | |
| | 683 | pub fn getDecl(ns: Namespace) *Decl { |
| | 684 | return ns.ty.getOwnerDecl(); |
| | 685 | } |
| 703 | }; | 686 | }; |
| 704 | | 687 | |
| 705 | pub const File = struct { | 688 | pub const File = struct { |
| ... | @@ -711,46 +694,54 @@ pub const Scope = struct { | ... | @@ -711,46 +694,54 @@ pub const Scope = struct { |
| 711 | unloaded_parse_failure, | 694 | unloaded_parse_failure, |
| 712 | loaded_success, | 695 | loaded_success, |
| 713 | }, | 696 | }, |
| 714 | | 697 | source_loaded: bool, |
| 715 | /// Relative to the owning package's root_src_dir. | 698 | /// Relative to the owning package's root_src_dir. |
| 716 | /// Reference to external memory, not owned by File. | 699 | /// Memory is stored in gpa, owned by File. |
| 717 | sub_file_path: []const u8, | 700 | sub_file_path: []const u8, |
| 718 | source: union(enum) { | 701 | /// Whether this is populated depends on `source_loaded`. |
| 719 | unloaded: void, | 702 | source: [:0]const u8, |
| 720 | bytes: [:0]const u8, | 703 | /// Whether this is populated depends on `status`. |
| 721 | }, | 704 | stat_size: u64, |
| | 705 | /// Whether this is populated depends on `status`. |
| | 706 | stat_inode: std.fs.File.INode, |
| | 707 | /// Whether this is populated depends on `status`. |
| | 708 | stat_mtime: i128, |
| | 709 | /// Whether this is populated depends on `status`. |
| | 710 | source_hash: Cache.BinDigest, |
| 722 | /// Whether this is populated or not depends on `status`. | 711 | /// Whether this is populated or not depends on `status`. |
| 723 | tree: ast.Tree, | 712 | tree: ast.Tree, |
| 724 | /// Package that this file is a part of, managed externally. | 713 | /// Package that this file is a part of, managed externally. |
| 725 | pkg: *Package, | 714 | pkg: *Package, |
| 726 | | 715 | /// The namespace of the struct that represents this file. |
| 727 | root_container: Container, | 716 | namespace: *Namespace, |
| 728 | | 717 | |
| 729 | pub fn unload(file: *File, gpa: *Allocator) void { | 718 | pub fn unload(file: *File, gpa: *Allocator) void { |
| 730 | switch (file.status) { | 719 | file.unloadTree(gpa); |
| 731 | .unloaded_parse_failure, | 720 | file.unloadSource(gpa); |
| 732 | .never_loaded, | 721 | } |
| 733 | .unloaded_success, | | |
| 734 | => { | | |
| 735 | file.status = .unloaded_success; | | |
| 736 | }, | | |
| 737 | | 722 | |
| 738 | .loaded_success => { | 723 | pub fn unloadTree(file: *File, gpa: *Allocator) void { |
| 739 | file.tree.deinit(gpa); | 724 | if (file.status == .loaded_success) { |
| 740 | file.status = .unloaded_success; | 725 | file.tree.deinit(gpa); |
| 741 | }, | | |
| 742 | } | 726 | } |
| 743 | switch (file.source) { | 727 | file.status = .unloaded_success; |
| 744 | .bytes => |bytes| { | 728 | } |
| 745 | gpa.free(bytes); | 729 | |
| 746 | file.source = .{ .unloaded = {} }; | 730 | pub fn unloadSource(file: *File, gpa: *Allocator) void { |
| 747 | }, | 731 | if (file.source_loaded) { |
| 748 | .unloaded => {}, | 732 | file.source_loaded = false; |
| | 733 | gpa.free(file.source); |
| | 734 | } |
| | 735 | } |
| | 736 | |
| | 737 | pub fn updateTreeToNewSource(file: *File) void { |
| | 738 | assert(file.source_loaded); |
| | 739 | if (file.status == .loaded_success) { |
| | 740 | file.tree.source = file.source; |
| 749 | } | 741 | } |
| 750 | } | 742 | } |
| 751 | | 743 | |
| 752 | pub fn deinit(file: *File, gpa: *Allocator) void { | 744 | pub fn deinit(file: *File, gpa: *Allocator) void { |
| 753 | file.root_container.deinit(gpa); | | |
| 754 | file.unload(gpa); | 745 | file.unload(gpa); |
| 755 | file.* = undefined; | 746 | file.* = undefined; |
| 756 | } | 747 | } |
| ... | @@ -765,22 +756,44 @@ pub const Scope = struct { | ... | @@ -765,22 +756,44 @@ pub const Scope = struct { |
| 765 | std.debug.print("{s}:{d}:{d}\n", .{ file.sub_file_path, loc.line + 1, loc.column + 1 }); | 756 | std.debug.print("{s}:{d}:{d}\n", .{ file.sub_file_path, loc.line + 1, loc.column + 1 }); |
| 766 | } | 757 | } |
| 767 | | 758 | |
| 768 | pub fn getSource(file: *File, module: *Module) ![:0]const u8 { | 759 | pub fn getSource(file: *File, gpa: *Allocator) ![:0]const u8 { |
| 769 | switch (file.source) { | 760 | if (file.source_loaded) return file.source; |
| 770 | .unloaded => { | 761 | |
| 771 | const source = try file.pkg.root_src_directory.handle.readFileAllocOptions( | 762 | // Keep track of inode, file size, mtime, hash so we can detect which files |
| 772 | module.gpa, | 763 | // have been modified when an incremental update is requested. |
| 773 | file.sub_file_path, | 764 | var f = try file.pkg.root_src_directory.handle.openFile(file.sub_file_path, .{}); |
| 774 | std.math.maxInt(u32), | 765 | defer f.close(); |
| 775 | null, | 766 | |
| 776 | 1, | 767 | const stat = try f.stat(); |
| 777 | 0, | 768 | |
| 778 | ); | 769 | try file.finishGettingSource(gpa, f, stat); |
| 779 | file.source = .{ .bytes = source }; | 770 | assert(file.source_loaded); |
| 780 | return source; | 771 | return file.source; |
| 781 | }, | 772 | } |
| 782 | .bytes => |bytes| return bytes, | 773 | |
| 783 | } | 774 | pub fn finishGettingSource( |
| | 775 | file: *File, |
| | 776 | gpa: *Allocator, |
| | 777 | f: std.fs.File, |
| | 778 | stat: std.fs.File.Stat, |
| | 779 | ) !void { |
| | 780 | if (stat.size > std.math.maxInt(u32)) |
| | 781 | return error.FileTooBig; |
| | 782 | |
| | 783 | const source = try gpa.allocSentinel(u8, stat.size, 0); |
| | 784 | const amt = try f.readAll(source); |
| | 785 | if (amt != stat.size) |
| | 786 | return error.UnexpectedEndOfFile; |
| | 787 | |
| | 788 | var hasher = Cache.hasher_init; |
| | 789 | hasher.update(source); |
| | 790 | hasher.final(&file.source_hash); |
| | 791 | |
| | 792 | file.stat_size = stat.size; |
| | 793 | file.stat_inode = stat.inode; |
| | 794 | file.stat_mtime = stat.mtime; |
| | 795 | file.source = source; |
| | 796 | file.source_loaded = true; |
| 784 | } | 797 | } |
| 785 | }; | 798 | }; |
| 786 | | 799 | |
| ... | @@ -859,7 +872,7 @@ pub const Scope = struct { | ... | @@ -859,7 +872,7 @@ pub const Scope = struct { |
| 859 | } | 872 | } |
| 860 | | 873 | |
| 861 | pub fn getFileScope(block: *Block) *Scope.File { | 874 | pub fn getFileScope(block: *Block) *Scope.File { |
| 862 | return block.src_decl.container.file_scope; | 875 | return block.src_decl.namespace.file_scope; |
| 863 | } | 876 | } |
| 864 | | 877 | |
| 865 | pub fn addNoOp( | 878 | pub fn addNoOp( |
| ... | @@ -1110,7 +1123,7 @@ pub const Scope = struct { | ... | @@ -1110,7 +1123,7 @@ pub const Scope = struct { |
| 1110 | } | 1123 | } |
| 1111 | | 1124 | |
| 1112 | pub fn tree(gz: *const GenZir) *const ast.Tree { | 1125 | pub fn tree(gz: *const GenZir) *const ast.Tree { |
| 1113 | return &gz.astgen.decl.container.file_scope.tree; | 1126 | return &gz.astgen.decl.namespace.file_scope.tree; |
| 1114 | } | 1127 | } |
| 1115 | | 1128 | |
| 1116 | pub fn setBreakResultLoc(gz: *GenZir, parent_rl: AstGen.ResultLoc) void { | 1129 | pub fn setBreakResultLoc(gz: *GenZir, parent_rl: AstGen.ResultLoc) void { |
| ... | @@ -1678,7 +1691,7 @@ pub const SrcLoc = struct { | ... | @@ -1678,7 +1691,7 @@ pub const SrcLoc = struct { |
| 1678 | .node_offset_switch_range, | 1691 | .node_offset_switch_range, |
| 1679 | .node_offset_fn_type_cc, | 1692 | .node_offset_fn_type_cc, |
| 1680 | .node_offset_fn_type_ret_ty, | 1693 | .node_offset_fn_type_ret_ty, |
| 1681 | => src_loc.container.decl.container.file_scope, | 1694 | => src_loc.container.decl.namespace.file_scope, |
| 1682 | }; | 1695 | }; |
| 1683 | } | 1696 | } |
| 1684 | | 1697 | |
| ... | @@ -1706,14 +1719,14 @@ pub const SrcLoc = struct { | ... | @@ -1706,14 +1719,14 @@ pub const SrcLoc = struct { |
| 1706 | .token_offset => |tok_off| { | 1719 | .token_offset => |tok_off| { |
| 1707 | const decl = src_loc.container.decl; | 1720 | const decl = src_loc.container.decl; |
| 1708 | const tok_index = decl.srcToken() + tok_off; | 1721 | const tok_index = decl.srcToken() + tok_off; |
| 1709 | const tree = decl.container.file_scope.base.tree(); | 1722 | const tree = decl.namespace.file_scope.base.tree(); |
| 1710 | const token_starts = tree.tokens.items(.start); | 1723 | const token_starts = tree.tokens.items(.start); |
| 1711 | return token_starts[tok_index]; | 1724 | return token_starts[tok_index]; |
| 1712 | }, | 1725 | }, |
| 1713 | .node_offset, .node_offset_bin_op => |node_off| { | 1726 | .node_offset, .node_offset_bin_op => |node_off| { |
| 1714 | const decl = src_loc.container.decl; | 1727 | const decl = src_loc.container.decl; |
| 1715 | const node = decl.relativeToNodeIndex(node_off); | 1728 | const node = decl.relativeToNodeIndex(node_off); |
| 1716 | const tree = decl.container.file_scope.base.tree(); | 1729 | const tree = decl.namespace.file_scope.base.tree(); |
| 1717 | const main_tokens = tree.nodes.items(.main_token); | 1730 | const main_tokens = tree.nodes.items(.main_token); |
| 1718 | const tok_index = main_tokens[node]; | 1731 | const tok_index = main_tokens[node]; |
| 1719 | const token_starts = tree.tokens.items(.start); | 1732 | const token_starts = tree.tokens.items(.start); |
| ... | @@ -1722,7 +1735,7 @@ pub const SrcLoc = struct { | ... | @@ -1722,7 +1735,7 @@ pub const SrcLoc = struct { |
| 1722 | .node_offset_back2tok => |node_off| { | 1735 | .node_offset_back2tok => |node_off| { |
| 1723 | const decl = src_loc.container.decl; | 1736 | const decl = src_loc.container.decl; |
| 1724 | const node = decl.relativeToNodeIndex(node_off); | 1737 | const node = decl.relativeToNodeIndex(node_off); |
| 1725 | const tree = decl.container.file_scope.base.tree(); | 1738 | const tree = decl.namespace.file_scope.base.tree(); |
| 1726 | const tok_index = tree.firstToken(node) - 2; | 1739 | const tok_index = tree.firstToken(node) - 2; |
| 1727 | const token_starts = tree.tokens.items(.start); | 1740 | const token_starts = tree.tokens.items(.start); |
| 1728 | return token_starts[tok_index]; | 1741 | return token_starts[tok_index]; |
| ... | @@ -1730,7 +1743,7 @@ pub const SrcLoc = struct { | ... | @@ -1730,7 +1743,7 @@ pub const SrcLoc = struct { |
| 1730 | .node_offset_var_decl_ty => |node_off| { | 1743 | .node_offset_var_decl_ty => |node_off| { |
| 1731 | const decl = src_loc.container.decl; | 1744 | const decl = src_loc.container.decl; |
| 1732 | const node = decl.relativeToNodeIndex(node_off); | 1745 | const node = decl.relativeToNodeIndex(node_off); |
| 1733 | const tree = decl.container.file_scope.base.tree(); | 1746 | const tree = decl.namespace.file_scope.base.tree(); |
| 1734 | const node_tags = tree.nodes.items(.tag); | 1747 | const node_tags = tree.nodes.items(.tag); |
| 1735 | const full = switch (node_tags[node]) { | 1748 | const full = switch (node_tags[node]) { |
| 1736 | .global_var_decl => tree.globalVarDecl(node), | 1749 | .global_var_decl => tree.globalVarDecl(node), |
| ... | @@ -1750,7 +1763,7 @@ pub const SrcLoc = struct { | ... | @@ -1750,7 +1763,7 @@ pub const SrcLoc = struct { |
| 1750 | }, | 1763 | }, |
| 1751 | .node_offset_builtin_call_arg0 => |node_off| { | 1764 | .node_offset_builtin_call_arg0 => |node_off| { |
| 1752 | const decl = src_loc.container.decl; | 1765 | const decl = src_loc.container.decl; |
| 1753 | const tree = decl.container.file_scope.base.tree(); | 1766 | const tree = decl.namespace.file_scope.base.tree(); |
| 1754 | const node_datas = tree.nodes.items(.data); | 1767 | const node_datas = tree.nodes.items(.data); |
| 1755 | const node_tags = tree.nodes.items(.tag); | 1768 | const node_tags = tree.nodes.items(.tag); |
| 1756 | const node = decl.relativeToNodeIndex(node_off); | 1769 | const node = decl.relativeToNodeIndex(node_off); |
| ... | @@ -1766,7 +1779,7 @@ pub const SrcLoc = struct { | ... | @@ -1766,7 +1779,7 @@ pub const SrcLoc = struct { |
| 1766 | }, | 1779 | }, |
| 1767 | .node_offset_builtin_call_arg1 => |node_off| { | 1780 | .node_offset_builtin_call_arg1 => |node_off| { |
| 1768 | const decl = src_loc.container.decl; | 1781 | const decl = src_loc.container.decl; |
| 1769 | const tree = decl.container.file_scope.base.tree(); | 1782 | const tree = decl.namespace.file_scope.base.tree(); |
| 1770 | const node_datas = tree.nodes.items(.data); | 1783 | const node_datas = tree.nodes.items(.data); |
| 1771 | const node_tags = tree.nodes.items(.tag); | 1784 | const node_tags = tree.nodes.items(.tag); |
| 1772 | const node = decl.relativeToNodeIndex(node_off); | 1785 | const node = decl.relativeToNodeIndex(node_off); |
| ... | @@ -1782,7 +1795,7 @@ pub const SrcLoc = struct { | ... | @@ -1782,7 +1795,7 @@ pub const SrcLoc = struct { |
| 1782 | }, | 1795 | }, |
| 1783 | .node_offset_array_access_index => |node_off| { | 1796 | .node_offset_array_access_index => |node_off| { |
| 1784 | const decl = src_loc.container.decl; | 1797 | const decl = src_loc.container.decl; |
| 1785 | const tree = decl.container.file_scope.base.tree(); | 1798 | const tree = decl.namespace.file_scope.base.tree(); |
| 1786 | const node_datas = tree.nodes.items(.data); | 1799 | const node_datas = tree.nodes.items(.data); |
| 1787 | const node_tags = tree.nodes.items(.tag); | 1800 | const node_tags = tree.nodes.items(.tag); |
| 1788 | const node = decl.relativeToNodeIndex(node_off); | 1801 | const node = decl.relativeToNodeIndex(node_off); |
| ... | @@ -1793,7 +1806,7 @@ pub const SrcLoc = struct { | ... | @@ -1793,7 +1806,7 @@ pub const SrcLoc = struct { |
| 1793 | }, | 1806 | }, |
| 1794 | .node_offset_slice_sentinel => |node_off| { | 1807 | .node_offset_slice_sentinel => |node_off| { |
| 1795 | const decl = src_loc.container.decl; | 1808 | const decl = src_loc.container.decl; |
| 1796 | const tree = decl.container.file_scope.base.tree(); | 1809 | const tree = decl.namespace.file_scope.base.tree(); |
| 1797 | const node_datas = tree.nodes.items(.data); | 1810 | const node_datas = tree.nodes.items(.data); |
| 1798 | const node_tags = tree.nodes.items(.tag); | 1811 | const node_tags = tree.nodes.items(.tag); |
| 1799 | const node = decl.relativeToNodeIndex(node_off); | 1812 | const node = decl.relativeToNodeIndex(node_off); |
| ... | @@ -1810,7 +1823,7 @@ pub const SrcLoc = struct { | ... | @@ -1810,7 +1823,7 @@ pub const SrcLoc = struct { |
| 1810 | }, | 1823 | }, |
| 1811 | .node_offset_call_func => |node_off| { | 1824 | .node_offset_call_func => |node_off| { |
| 1812 | const decl = src_loc.container.decl; | 1825 | const decl = src_loc.container.decl; |
| 1813 | const tree = decl.container.file_scope.base.tree(); | 1826 | const tree = decl.namespace.file_scope.base.tree(); |
| 1814 | const node_datas = tree.nodes.items(.data); | 1827 | const node_datas = tree.nodes.items(.data); |
| 1815 | const node_tags = tree.nodes.items(.tag); | 1828 | const node_tags = tree.nodes.items(.tag); |
| 1816 | const node = decl.relativeToNodeIndex(node_off); | 1829 | const node = decl.relativeToNodeIndex(node_off); |
| ... | @@ -1837,7 +1850,7 @@ pub const SrcLoc = struct { | ... | @@ -1837,7 +1850,7 @@ pub const SrcLoc = struct { |
| 1837 | }, | 1850 | }, |
| 1838 | .node_offset_field_name => |node_off| { | 1851 | .node_offset_field_name => |node_off| { |
| 1839 | const decl = src_loc.container.decl; | 1852 | const decl = src_loc.container.decl; |
| 1840 | const tree = decl.container.file_scope.base.tree(); | 1853 | const tree = decl.namespace.file_scope.base.tree(); |
| 1841 | const node_datas = tree.nodes.items(.data); | 1854 | const node_datas = tree.nodes.items(.data); |
| 1842 | const node_tags = tree.nodes.items(.tag); | 1855 | const node_tags = tree.nodes.items(.tag); |
| 1843 | const node = decl.relativeToNodeIndex(node_off); | 1856 | const node = decl.relativeToNodeIndex(node_off); |
| ... | @@ -1850,7 +1863,7 @@ pub const SrcLoc = struct { | ... | @@ -1850,7 +1863,7 @@ pub const SrcLoc = struct { |
| 1850 | }, | 1863 | }, |
| 1851 | .node_offset_deref_ptr => |node_off| { | 1864 | .node_offset_deref_ptr => |node_off| { |
| 1852 | const decl = src_loc.container.decl; | 1865 | const decl = src_loc.container.decl; |
| 1853 | const tree = decl.container.file_scope.base.tree(); | 1866 | const tree = decl.namespace.file_scope.base.tree(); |
| 1854 | const node_datas = tree.nodes.items(.data); | 1867 | const node_datas = tree.nodes.items(.data); |
| 1855 | const node_tags = tree.nodes.items(.tag); | 1868 | const node_tags = tree.nodes.items(.tag); |
| 1856 | const node = decl.relativeToNodeIndex(node_off); | 1869 | const node = decl.relativeToNodeIndex(node_off); |
| ... | @@ -1860,7 +1873,7 @@ pub const SrcLoc = struct { | ... | @@ -1860,7 +1873,7 @@ pub const SrcLoc = struct { |
| 1860 | }, | 1873 | }, |
| 1861 | .node_offset_asm_source => |node_off| { | 1874 | .node_offset_asm_source => |node_off| { |
| 1862 | const decl = src_loc.container.decl; | 1875 | const decl = src_loc.container.decl; |
| 1863 | const tree = decl.container.file_scope.base.tree(); | 1876 | const tree = decl.namespace.file_scope.base.tree(); |
| 1864 | const node_datas = tree.nodes.items(.data); | 1877 | const node_datas = tree.nodes.items(.data); |
| 1865 | const node_tags = tree.nodes.items(.tag); | 1878 | const node_tags = tree.nodes.items(.tag); |
| 1866 | const node = decl.relativeToNodeIndex(node_off); | 1879 | const node = decl.relativeToNodeIndex(node_off); |
| ... | @@ -1876,7 +1889,7 @@ pub const SrcLoc = struct { | ... | @@ -1876,7 +1889,7 @@ pub const SrcLoc = struct { |
| 1876 | }, | 1889 | }, |
| 1877 | .node_offset_asm_ret_ty => |node_off| { | 1890 | .node_offset_asm_ret_ty => |node_off| { |
| 1878 | const decl = src_loc.container.decl; | 1891 | const decl = src_loc.container.decl; |
| 1879 | const tree = decl.container.file_scope.base.tree(); | 1892 | const tree = decl.namespace.file_scope.base.tree(); |
| 1880 | const node_datas = tree.nodes.items(.data); | 1893 | const node_datas = tree.nodes.items(.data); |
| 1881 | const node_tags = tree.nodes.items(.tag); | 1894 | const node_tags = tree.nodes.items(.tag); |
| 1882 | const node = decl.relativeToNodeIndex(node_off); | 1895 | const node = decl.relativeToNodeIndex(node_off); |
| ... | @@ -1894,7 +1907,7 @@ pub const SrcLoc = struct { | ... | @@ -1894,7 +1907,7 @@ pub const SrcLoc = struct { |
| 1894 | .node_offset_for_cond, .node_offset_if_cond => |node_off| { | 1907 | .node_offset_for_cond, .node_offset_if_cond => |node_off| { |
| 1895 | const decl = src_loc.container.decl; | 1908 | const decl = src_loc.container.decl; |
| 1896 | const node = decl.relativeToNodeIndex(node_off); | 1909 | const node = decl.relativeToNodeIndex(node_off); |
| 1897 | const tree = decl.container.file_scope.base.tree(); | 1910 | const tree = decl.namespace.file_scope.base.tree(); |
| 1898 | const node_tags = tree.nodes.items(.tag); | 1911 | const node_tags = tree.nodes.items(.tag); |
| 1899 | const src_node = switch (node_tags[node]) { | 1912 | const src_node = switch (node_tags[node]) { |
| 1900 | .if_simple => tree.ifSimple(node).ast.cond_expr, | 1913 | .if_simple => tree.ifSimple(node).ast.cond_expr, |
| ... | @@ -1914,7 +1927,7 @@ pub const SrcLoc = struct { | ... | @@ -1914,7 +1927,7 @@ pub const SrcLoc = struct { |
| 1914 | .node_offset_bin_lhs => |node_off| { | 1927 | .node_offset_bin_lhs => |node_off| { |
| 1915 | const decl = src_loc.container.decl; | 1928 | const decl = src_loc.container.decl; |
| 1916 | const node = decl.relativeToNodeIndex(node_off); | 1929 | const node = decl.relativeToNodeIndex(node_off); |
| 1917 | const tree = decl.container.file_scope.base.tree(); | 1930 | const tree = decl.namespace.file_scope.base.tree(); |
| 1918 | const node_datas = tree.nodes.items(.data); | 1931 | const node_datas = tree.nodes.items(.data); |
| 1919 | const src_node = node_datas[node].lhs; | 1932 | const src_node = node_datas[node].lhs; |
| 1920 | const main_tokens = tree.nodes.items(.main_token); | 1933 | const main_tokens = tree.nodes.items(.main_token); |
| ... | @@ -1925,7 +1938,7 @@ pub const SrcLoc = struct { | ... | @@ -1925,7 +1938,7 @@ pub const SrcLoc = struct { |
| 1925 | .node_offset_bin_rhs => |node_off| { | 1938 | .node_offset_bin_rhs => |node_off| { |
| 1926 | const decl = src_loc.container.decl; | 1939 | const decl = src_loc.container.decl; |
| 1927 | const node = decl.relativeToNodeIndex(node_off); | 1940 | const node = decl.relativeToNodeIndex(node_off); |
| 1928 | const tree = decl.container.file_scope.base.tree(); | 1941 | const tree = decl.namespace.file_scope.base.tree(); |
| 1929 | const node_datas = tree.nodes.items(.data); | 1942 | const node_datas = tree.nodes.items(.data); |
| 1930 | const src_node = node_datas[node].rhs; | 1943 | const src_node = node_datas[node].rhs; |
| 1931 | const main_tokens = tree.nodes.items(.main_token); | 1944 | const main_tokens = tree.nodes.items(.main_token); |
| ... | @@ -1937,7 +1950,7 @@ pub const SrcLoc = struct { | ... | @@ -1937,7 +1950,7 @@ pub const SrcLoc = struct { |
| 1937 | .node_offset_switch_operand => |node_off| { | 1950 | .node_offset_switch_operand => |node_off| { |
| 1938 | const decl = src_loc.container.decl; | 1951 | const decl = src_loc.container.decl; |
| 1939 | const node = decl.relativeToNodeIndex(node_off); | 1952 | const node = decl.relativeToNodeIndex(node_off); |
| 1940 | const tree = decl.container.file_scope.base.tree(); | 1953 | const tree = decl.namespace.file_scope.base.tree(); |
| 1941 | const node_datas = tree.nodes.items(.data); | 1954 | const node_datas = tree.nodes.items(.data); |
| 1942 | const src_node = node_datas[node].lhs; | 1955 | const src_node = node_datas[node].lhs; |
| 1943 | const main_tokens = tree.nodes.items(.main_token); | 1956 | const main_tokens = tree.nodes.items(.main_token); |
| ... | @@ -1949,7 +1962,7 @@ pub const SrcLoc = struct { | ... | @@ -1949,7 +1962,7 @@ pub const SrcLoc = struct { |
| 1949 | .node_offset_switch_special_prong => |node_off| { | 1962 | .node_offset_switch_special_prong => |node_off| { |
| 1950 | const decl = src_loc.container.decl; | 1963 | const decl = src_loc.container.decl; |
| 1951 | const switch_node = decl.relativeToNodeIndex(node_off); | 1964 | const switch_node = decl.relativeToNodeIndex(node_off); |
| 1952 | const tree = decl.container.file_scope.base.tree(); | 1965 | const tree = decl.namespace.file_scope.base.tree(); |
| 1953 | const node_datas = tree.nodes.items(.data); | 1966 | const node_datas = tree.nodes.items(.data); |
| 1954 | const node_tags = tree.nodes.items(.tag); | 1967 | const node_tags = tree.nodes.items(.tag); |
| 1955 | const main_tokens = tree.nodes.items(.main_token); | 1968 | const main_tokens = tree.nodes.items(.main_token); |
| ... | @@ -1976,7 +1989,7 @@ pub const SrcLoc = struct { | ... | @@ -1976,7 +1989,7 @@ pub const SrcLoc = struct { |
| 1976 | .node_offset_switch_range => |node_off| { | 1989 | .node_offset_switch_range => |node_off| { |
| 1977 | const decl = src_loc.container.decl; | 1990 | const decl = src_loc.container.decl; |
| 1978 | const switch_node = decl.relativeToNodeIndex(node_off); | 1991 | const switch_node = decl.relativeToNodeIndex(node_off); |
| 1979 | const tree = decl.container.file_scope.base.tree(); | 1992 | const tree = decl.namespace.file_scope.base.tree(); |
| 1980 | const node_datas = tree.nodes.items(.data); | 1993 | const node_datas = tree.nodes.items(.data); |
| 1981 | const node_tags = tree.nodes.items(.tag); | 1994 | const node_tags = tree.nodes.items(.tag); |
| 1982 | const main_tokens = tree.nodes.items(.main_token); | 1995 | const main_tokens = tree.nodes.items(.main_token); |
| ... | @@ -2006,7 +2019,7 @@ pub const SrcLoc = struct { | ... | @@ -2006,7 +2019,7 @@ pub const SrcLoc = struct { |
| 2006 | | 2019 | |
| 2007 | .node_offset_fn_type_cc => |node_off| { | 2020 | .node_offset_fn_type_cc => |node_off| { |
| 2008 | const decl = src_loc.container.decl; | 2021 | const decl = src_loc.container.decl; |
| 2009 | const tree = decl.container.file_scope.base.tree(); | 2022 | const tree = decl.namespace.file_scope.base.tree(); |
| 2010 | const node_datas = tree.nodes.items(.data); | 2023 | const node_datas = tree.nodes.items(.data); |
| 2011 | const node_tags = tree.nodes.items(.tag); | 2024 | const node_tags = tree.nodes.items(.tag); |
| 2012 | const node = decl.relativeToNodeIndex(node_off); | 2025 | const node = decl.relativeToNodeIndex(node_off); |
| ... | @@ -2026,7 +2039,7 @@ pub const SrcLoc = struct { | ... | @@ -2026,7 +2039,7 @@ pub const SrcLoc = struct { |
| 2026 | | 2039 | |
| 2027 | .node_offset_fn_type_ret_ty => |node_off| { | 2040 | .node_offset_fn_type_ret_ty => |node_off| { |
| 2028 | const decl = src_loc.container.decl; | 2041 | const decl = src_loc.container.decl; |
| 2029 | const tree = decl.container.file_scope.base.tree(); | 2042 | const tree = decl.namespace.file_scope.base.tree(); |
| 2030 | const node_datas = tree.nodes.items(.data); | 2043 | const node_datas = tree.nodes.items(.data); |
| 2031 | const node_tags = tree.nodes.items(.tag); | 2044 | const node_tags = tree.nodes.items(.tag); |
| 2032 | const node = decl.relativeToNodeIndex(node_off); | 2045 | const node = decl.relativeToNodeIndex(node_off); |
| ... | @@ -2351,7 +2364,6 @@ pub fn deinit(mod: *Module) void { | ... | @@ -2351,7 +2364,6 @@ pub fn deinit(mod: *Module) void { |
| 2351 | mod.export_owners.deinit(gpa); | 2364 | mod.export_owners.deinit(gpa); |
| 2352 | | 2365 | |
| 2353 | mod.symbol_exports.deinit(gpa); | 2366 | mod.symbol_exports.deinit(gpa); |
| 2354 | mod.root_scope.destroy(gpa); | | |
| 2355 | | 2367 | |
| 2356 | var it = mod.global_error_set.iterator(); | 2368 | var it = mod.global_error_set.iterator(); |
| 2357 | while (it.next()) |entry| { | 2369 | while (it.next()) |entry| { |
| ... | @@ -2362,6 +2374,7 @@ pub fn deinit(mod: *Module) void { | ... | @@ -2362,6 +2374,7 @@ pub fn deinit(mod: *Module) void { |
| 2362 | mod.error_name_list.deinit(gpa); | 2374 | mod.error_name_list.deinit(gpa); |
| 2363 | | 2375 | |
| 2364 | for (mod.import_table.items()) |entry| { | 2376 | for (mod.import_table.items()) |entry| { |
| | 2377 | gpa.free(entry.key); |
| 2365 | entry.value.destroy(gpa); | 2378 | entry.value.destroy(gpa); |
| 2366 | } | 2379 | } |
| 2367 | mod.import_table.deinit(gpa); | 2380 | mod.import_table.deinit(gpa); |
| ... | @@ -2465,7 +2478,7 @@ fn astgenAndSemaDecl(mod: *Module, decl: *Decl) !bool { | ... | @@ -2465,7 +2478,7 @@ fn astgenAndSemaDecl(mod: *Module, decl: *Decl) !bool { |
| 2465 | const tracy = trace(@src()); | 2478 | const tracy = trace(@src()); |
| 2466 | defer tracy.end(); | 2479 | defer tracy.end(); |
| 2467 | | 2480 | |
| 2468 | const tree = try mod.getAstTree(decl.container.file_scope); | 2481 | const tree = try mod.getAstTree(decl.namespace.file_scope); |
| 2469 | const node_tags = tree.nodes.items(.tag); | 2482 | const node_tags = tree.nodes.items(.tag); |
| 2470 | const node_datas = tree.nodes.items(.data); | 2483 | const node_datas = tree.nodes.items(.data); |
| 2471 | const decl_node = decl.src_node; | 2484 | const decl_node = decl.src_node; |
| ... | @@ -2516,7 +2529,7 @@ fn astgenAndSemaDecl(mod: *Module, decl: *Decl) !bool { | ... | @@ -2516,7 +2529,7 @@ fn astgenAndSemaDecl(mod: *Module, decl: *Decl) !bool { |
| 2516 | | 2529 | |
| 2517 | var gen_scope: Scope.GenZir = .{ | 2530 | var gen_scope: Scope.GenZir = .{ |
| 2518 | .force_comptime = true, | 2531 | .force_comptime = true, |
| 2519 | .parent = &decl.container.base, | 2532 | .parent = &decl.namespace.base, |
| 2520 | .astgen = &astgen, | 2533 | .astgen = &astgen, |
| 2521 | }; | 2534 | }; |
| 2522 | defer gen_scope.instructions.deinit(mod.gpa); | 2535 | defer gen_scope.instructions.deinit(mod.gpa); |
| ... | @@ -2590,7 +2603,7 @@ fn astgenAndSemaFn( | ... | @@ -2590,7 +2603,7 @@ fn astgenAndSemaFn( |
| 2590 | | 2603 | |
| 2591 | var fn_type_scope: Scope.GenZir = .{ | 2604 | var fn_type_scope: Scope.GenZir = .{ |
| 2592 | .force_comptime = true, | 2605 | .force_comptime = true, |
| 2593 | .parent = &decl.container.base, | 2606 | .parent = &decl.namespace.base, |
| 2594 | .astgen = &fn_type_astgen, | 2607 | .astgen = &fn_type_astgen, |
| 2595 | }; | 2608 | }; |
| 2596 | defer fn_type_scope.instructions.deinit(mod.gpa); | 2609 | defer fn_type_scope.instructions.deinit(mod.gpa); |
| ... | @@ -2829,7 +2842,7 @@ fn astgenAndSemaFn( | ... | @@ -2829,7 +2842,7 @@ fn astgenAndSemaFn( |
| 2829 | | 2842 | |
| 2830 | var gen_scope: Scope.GenZir = .{ | 2843 | var gen_scope: Scope.GenZir = .{ |
| 2831 | .force_comptime = false, | 2844 | .force_comptime = false, |
| 2832 | .parent = &decl.container.base, | 2845 | .parent = &decl.namespace.base, |
| 2833 | .astgen = &astgen, | 2846 | .astgen = &astgen, |
| 2834 | }; | 2847 | }; |
| 2835 | defer gen_scope.instructions.deinit(mod.gpa); | 2848 | defer gen_scope.instructions.deinit(mod.gpa); |
| ... | @@ -3035,7 +3048,7 @@ fn astgenAndSemaVarDecl( | ... | @@ -3035,7 +3048,7 @@ fn astgenAndSemaVarDecl( |
| 3035 | | 3048 | |
| 3036 | var gen_scope: Scope.GenZir = .{ | 3049 | var gen_scope: Scope.GenZir = .{ |
| 3037 | .force_comptime = true, | 3050 | .force_comptime = true, |
| 3038 | .parent = &decl.container.base, | 3051 | .parent = &decl.namespace.base, |
| 3039 | .astgen = &astgen, | 3052 | .astgen = &astgen, |
| 3040 | }; | 3053 | }; |
| 3041 | defer gen_scope.instructions.deinit(mod.gpa); | 3054 | defer gen_scope.instructions.deinit(mod.gpa); |
| ... | @@ -3104,7 +3117,7 @@ fn astgenAndSemaVarDecl( | ... | @@ -3104,7 +3117,7 @@ fn astgenAndSemaVarDecl( |
| 3104 | | 3117 | |
| 3105 | var type_scope: Scope.GenZir = .{ | 3118 | var type_scope: Scope.GenZir = .{ |
| 3106 | .force_comptime = true, | 3119 | .force_comptime = true, |
| 3107 | .parent = &decl.container.base, | 3120 | .parent = &decl.namespace.base, |
| 3108 | .astgen = &astgen, | 3121 | .astgen = &astgen, |
| 3109 | }; | 3122 | }; |
| 3110 | defer type_scope.instructions.deinit(mod.gpa); | 3123 | defer type_scope.instructions.deinit(mod.gpa); |
| ... | @@ -3220,46 +3233,48 @@ pub fn declareDeclDependency(mod: *Module, depender: *Decl, dependee: *Decl) !u3 | ... | @@ -3220,46 +3233,48 @@ pub fn declareDeclDependency(mod: *Module, depender: *Decl, dependee: *Decl) !u3 |
| 3220 | return @intCast(u32, gop.index); | 3233 | return @intCast(u32, gop.index); |
| 3221 | } | 3234 | } |
| 3222 | | 3235 | |
| 3223 | pub fn getAstTree(mod: *Module, root_scope: *Scope.File) !*const ast.Tree { | 3236 | pub fn getAstTree(mod: *Module, file: *Scope.File) !*const ast.Tree { |
| 3224 | const tracy = trace(@src()); | 3237 | const tracy = trace(@src()); |
| 3225 | defer tracy.end(); | 3238 | defer tracy.end(); |
| 3226 | | 3239 | |
| 3227 | switch (root_scope.status) { | 3240 | switch (file.status) { |
| 3228 | .never_loaded, .unloaded_success => { | 3241 | .never_loaded, .unloaded_success => { |
| 3229 | try mod.failed_files.ensureCapacity(mod.gpa, mod.failed_files.items().len + 1); | 3242 | const gpa = mod.gpa; |
| | 3243 | |
| | 3244 | try mod.failed_files.ensureCapacity(gpa, mod.failed_files.items().len + 1); |
| 3230 | | 3245 | |
| 3231 | const source = try root_scope.getSource(mod); | 3246 | const source = try file.getSource(gpa); |
| 3232 | | 3247 | |
| 3233 | var keep_tree = false; | 3248 | var keep_tree = false; |
| 3234 | root_scope.tree = try std.zig.parse(mod.gpa, source); | 3249 | file.tree = try std.zig.parse(gpa, source); |
| 3235 | defer if (!keep_tree) root_scope.tree.deinit(mod.gpa); | 3250 | defer if (!keep_tree) file.tree.deinit(gpa); |
| 3236 | | 3251 | |
| 3237 | const tree = &root_scope.tree; | 3252 | const tree = &file.tree; |
| 3238 | | 3253 | |
| 3239 | if (tree.errors.len != 0) { | 3254 | if (tree.errors.len != 0) { |
| 3240 | const parse_err = tree.errors[0]; | 3255 | const parse_err = tree.errors[0]; |
| 3241 | | 3256 | |
| 3242 | var msg = std.ArrayList(u8).init(mod.gpa); | 3257 | var msg = std.ArrayList(u8).init(gpa); |
| 3243 | defer msg.deinit(); | 3258 | defer msg.deinit(); |
| 3244 | | 3259 | |
| 3245 | const token_starts = tree.tokens.items(.start); | 3260 | const token_starts = tree.tokens.items(.start); |
| 3246 | | 3261 | |
| 3247 | try tree.renderError(parse_err, msg.writer()); | 3262 | try tree.renderError(parse_err, msg.writer()); |
| 3248 | const err_msg = try mod.gpa.create(ErrorMsg); | 3263 | const err_msg = try gpa.create(ErrorMsg); |
| 3249 | err_msg.* = .{ | 3264 | err_msg.* = .{ |
| 3250 | .src_loc = .{ | 3265 | .src_loc = .{ |
| 3251 | .container = .{ .file_scope = root_scope }, | 3266 | .container = .{ .file_scope = file }, |
| 3252 | .lazy = .{ .byte_abs = token_starts[parse_err.token] }, | 3267 | .lazy = .{ .byte_abs = token_starts[parse_err.token] }, |
| 3253 | }, | 3268 | }, |
| 3254 | .msg = msg.toOwnedSlice(), | 3269 | .msg = msg.toOwnedSlice(), |
| 3255 | }; | 3270 | }; |
| 3256 | | 3271 | |
| 3257 | mod.failed_files.putAssumeCapacityNoClobber(root_scope, err_msg); | 3272 | mod.failed_files.putAssumeCapacityNoClobber(file, err_msg); |
| 3258 | root_scope.status = .unloaded_parse_failure; | 3273 | file.status = .unloaded_parse_failure; |
| 3259 | return error.AnalysisFail; | 3274 | return error.AnalysisFail; |
| 3260 | } | 3275 | } |
| 3261 | | 3276 | |
| 3262 | root_scope.status = .loaded_success; | 3277 | file.status = .loaded_success; |
| 3263 | keep_tree = true; | 3278 | keep_tree = true; |
| 3264 | | 3279 | |
| 3265 | return tree; | 3280 | return tree; |
| ... | @@ -3267,30 +3282,186 @@ pub fn getAstTree(mod: *Module, root_scope: *Scope.File) !*const ast.Tree { | ... | @@ -3267,30 +3282,186 @@ pub fn getAstTree(mod: *Module, root_scope: *Scope.File) !*const ast.Tree { |
| 3267 | | 3282 | |
| 3268 | .unloaded_parse_failure => return error.AnalysisFail, | 3283 | .unloaded_parse_failure => return error.AnalysisFail, |
| 3269 | | 3284 | |
| 3270 | .loaded_success => return &root_scope.tree, | 3285 | .loaded_success => return &file.tree, |
| 3271 | } | 3286 | } |
| 3272 | } | 3287 | } |
| 3273 | | 3288 | |
| 3274 | pub fn analyzeContainer(mod: *Module, container_scope: *Scope.Container) !void { | 3289 | pub fn importFile(mod: *Module, cur_pkg: *Package, import_string: []const u8) !*Scope.File { |
| | 3290 | const gpa = mod.gpa; |
| | 3291 | |
| | 3292 | const cur_pkg_dir_path = cur_pkg.root_src_directory.path orelse "."; |
| | 3293 | const found_pkg = cur_pkg.table.get(import_string); |
| | 3294 | |
| | 3295 | const resolved_path = if (found_pkg) |pkg| |
| | 3296 | try std.fs.path.resolve(gpa, &[_][]const u8{ pkg.root_src_directory.path orelse ".", pkg.root_src_path }) |
| | 3297 | else |
| | 3298 | try std.fs.path.resolve(gpa, &[_][]const u8{ cur_pkg_dir_path, import_string }); |
| | 3299 | var keep_resolved_path = false; |
| | 3300 | defer if (!keep_resolved_path) gpa.free(resolved_path); |
| | 3301 | |
| | 3302 | const gop = try mod.import_table.getOrPut(gpa, resolved_path); |
| | 3303 | if (gop.found_existing) return gop.entry.value; |
| | 3304 | |
| | 3305 | if (found_pkg == null) { |
| | 3306 | const resolved_root_path = try std.fs.path.resolve(gpa, &[_][]const u8{cur_pkg_dir_path}); |
| | 3307 | defer gpa.free(resolved_root_path); |
| | 3308 | |
| | 3309 | if (!mem.startsWith(u8, resolved_path, resolved_root_path)) { |
| | 3310 | return error.ImportOutsidePkgPath; |
| | 3311 | } |
| | 3312 | } |
| | 3313 | |
| | 3314 | const new_file = try gpa.create(Scope.File); |
| | 3315 | gop.entry.value = new_file; |
| | 3316 | new_file.* = .{ |
| | 3317 | .sub_file_path = resolved_path, |
| | 3318 | .source = undefined, |
| | 3319 | .source_hash = undefined, |
| | 3320 | .source_loaded = false, |
| | 3321 | .stat_size = undefined, |
| | 3322 | .stat_inode = undefined, |
| | 3323 | .stat_mtime = undefined, |
| | 3324 | .tree = undefined, |
| | 3325 | .status = .never_loaded, |
| | 3326 | .pkg = found_pkg orelse cur_pkg, |
| | 3327 | .namespace = undefined, |
| | 3328 | }; |
| | 3329 | keep_resolved_path = true; |
| | 3330 | |
| | 3331 | const tree = try mod.getAstTree(new_file); |
| | 3332 | |
| | 3333 | const parent_name_hash: Scope.NameHash = if (found_pkg) |pkg| |
| | 3334 | pkg.namespace_hash |
| | 3335 | else |
| | 3336 | std.zig.hashName(cur_pkg.namespace_hash, "/", resolved_path); |
| | 3337 | |
| | 3338 | // We need a Decl to pass to AstGen and collect dependencies. But ultimately we |
| | 3339 | // want to pass them on to the Decl for the struct that represents the file. |
| | 3340 | var tmp_namespace: Scope.Namespace = .{ |
| | 3341 | .parent = null, |
| | 3342 | .file_scope = new_file, |
| | 3343 | .parent_name_hash = parent_name_hash, |
| | 3344 | .ty = Type.initTag(.type), |
| | 3345 | }; |
| | 3346 | const top_decl = try mod.createNewDecl( |
| | 3347 | &tmp_namespace, |
| | 3348 | resolved_path, |
| | 3349 | 0, |
| | 3350 | parent_name_hash, |
| | 3351 | new_file.source_hash, |
| | 3352 | ); |
| | 3353 | defer { |
| | 3354 | mod.decl_table.removeAssertDiscard(parent_name_hash); |
| | 3355 | top_decl.destroy(mod); |
| | 3356 | } |
| | 3357 | |
| | 3358 | var gen_scope_arena = std.heap.ArenaAllocator.init(gpa); |
| | 3359 | defer gen_scope_arena.deinit(); |
| | 3360 | |
| | 3361 | var astgen = try AstGen.init(mod, top_decl, &gen_scope_arena.allocator); |
| | 3362 | defer astgen.deinit(); |
| | 3363 | |
| | 3364 | var gen_scope: Scope.GenZir = .{ |
| | 3365 | .force_comptime = true, |
| | 3366 | .parent = &new_file.base, |
| | 3367 | .astgen = &astgen, |
| | 3368 | }; |
| | 3369 | defer gen_scope.instructions.deinit(gpa); |
| | 3370 | |
| | 3371 | const container_decl: ast.full.ContainerDecl = .{ |
| | 3372 | .layout_token = null, |
| | 3373 | .ast = .{ |
| | 3374 | .main_token = undefined, |
| | 3375 | .enum_token = null, |
| | 3376 | .members = tree.rootDecls(), |
| | 3377 | .arg = 0, |
| | 3378 | }, |
| | 3379 | }; |
| | 3380 | |
| | 3381 | const struct_decl_ref = try AstGen.structDeclInner( |
| | 3382 | &gen_scope, |
| | 3383 | &gen_scope.base, |
| | 3384 | 0, |
| | 3385 | container_decl, |
| | 3386 | .struct_decl, |
| | 3387 | ); |
| | 3388 | _ = try gen_scope.addBreak(.break_inline, 0, struct_decl_ref); |
| | 3389 | |
| | 3390 | var code = try gen_scope.finish(); |
| | 3391 | defer code.deinit(gpa); |
| | 3392 | if (std.builtin.mode == .Debug and mod.comp.verbose_ir) { |
| | 3393 | code.dump(gpa, "import", &gen_scope.base, 0) catch {}; |
| | 3394 | } |
| | 3395 | |
| | 3396 | var sema: Sema = .{ |
| | 3397 | .mod = mod, |
| | 3398 | .gpa = gpa, |
| | 3399 | .arena = &gen_scope_arena.allocator, |
| | 3400 | .code = code, |
| | 3401 | .inst_map = try gen_scope_arena.allocator.alloc(*ir.Inst, code.instructions.len), |
| | 3402 | .owner_decl = top_decl, |
| | 3403 | .func = null, |
| | 3404 | .owner_func = null, |
| | 3405 | .param_inst_list = &.{}, |
| | 3406 | }; |
| | 3407 | var block_scope: Scope.Block = .{ |
| | 3408 | .parent = null, |
| | 3409 | .sema = &sema, |
| | 3410 | .src_decl = top_decl, |
| | 3411 | .instructions = .{}, |
| | 3412 | .inlining = null, |
| | 3413 | .is_comptime = true, |
| | 3414 | }; |
| | 3415 | defer block_scope.instructions.deinit(gpa); |
| | 3416 | |
| | 3417 | const init_inst_zir_ref = try sema.rootAsRef(&block_scope); |
| | 3418 | const analyzed_struct_inst = try sema.resolveInst(init_inst_zir_ref); |
| | 3419 | assert(analyzed_struct_inst.ty.zigTypeTag() == .Type); |
| | 3420 | const val = analyzed_struct_inst.value().?; |
| | 3421 | const struct_ty = try val.toType(&gen_scope_arena.allocator); |
| | 3422 | const struct_decl = struct_ty.getOwnerDecl(); |
| | 3423 | |
| | 3424 | new_file.namespace = struct_ty.getNamespace().?; |
| | 3425 | new_file.namespace.parent = null; |
| | 3426 | new_file.namespace.parent_name_hash = tmp_namespace.parent_name_hash; |
| | 3427 | |
| | 3428 | // Transfer the dependencies to `owner_decl`. |
| | 3429 | assert(top_decl.dependants.count() == 0); |
| | 3430 | for (top_decl.dependencies.items()) |entry| { |
| | 3431 | const dep = entry.key; |
| | 3432 | dep.removeDependant(top_decl); |
| | 3433 | if (dep == struct_decl) continue; |
| | 3434 | _ = try mod.declareDeclDependency(struct_decl, dep); |
| | 3435 | } |
| | 3436 | |
| | 3437 | try mod.analyzeFile(new_file); |
| | 3438 | return new_file; |
| | 3439 | } |
| | 3440 | |
| | 3441 | pub fn analyzeFile(mod: *Module, file: *Scope.File) !void { |
| | 3442 | return mod.analyzeNamespace(file.namespace); |
| | 3443 | } |
| | 3444 | |
| | 3445 | pub fn analyzeNamespace(mod: *Module, namespace: *Scope.Namespace) !void { |
| 3275 | const tracy = trace(@src()); | 3446 | const tracy = trace(@src()); |
| 3276 | defer tracy.end(); | 3447 | defer tracy.end(); |
| 3277 | | 3448 | |
| 3278 | // We may be analyzing it for the first time, or this may be | 3449 | // We may be analyzing it for the first time, or this may be |
| 3279 | // an incremental update. This code handles both cases. | 3450 | // an incremental update. This code handles both cases. |
| 3280 | const tree = try mod.getAstTree(container_scope.file_scope); | 3451 | const tree = try mod.getAstTree(namespace.file_scope); |
| 3281 | const node_tags = tree.nodes.items(.tag); | 3452 | const node_tags = tree.nodes.items(.tag); |
| 3282 | const node_datas = tree.nodes.items(.data); | 3453 | const node_datas = tree.nodes.items(.data); |
| 3283 | const decls = tree.rootDecls(); | 3454 | const decls = tree.rootDecls(); |
| 3284 | | 3455 | |
| 3285 | try mod.comp.work_queue.ensureUnusedCapacity(decls.len); | 3456 | try mod.comp.work_queue.ensureUnusedCapacity(decls.len); |
| 3286 | try container_scope.decls.ensureCapacity(mod.gpa, decls.len); | 3457 | try namespace.decls.ensureCapacity(mod.gpa, decls.len); |
| 3287 | | 3458 | |
| 3288 | // Keep track of the decls that we expect to see in this file so that | 3459 | // Keep track of the decls that we expect to see in this namespace so that |
| 3289 | // we know which ones have been deleted. | 3460 | // we know which ones have been deleted. |
| 3290 | var deleted_decls = std.AutoArrayHashMap(*Decl, void).init(mod.gpa); | 3461 | var deleted_decls = std.AutoArrayHashMap(*Decl, void).init(mod.gpa); |
| 3291 | defer deleted_decls.deinit(); | 3462 | defer deleted_decls.deinit(); |
| 3292 | try deleted_decls.ensureCapacity(container_scope.decls.items().len); | 3463 | try deleted_decls.ensureCapacity(namespace.decls.items().len); |
| 3293 | for (container_scope.decls.items()) |entry| { | 3464 | for (namespace.decls.items()) |entry| { |
| 3294 | deleted_decls.putAssumeCapacityNoClobber(entry.key, {}); | 3465 | deleted_decls.putAssumeCapacityNoClobber(entry.key, {}); |
| 3295 | } | 3466 | } |
| 3296 | | 3467 | |
| ... | @@ -3310,7 +3481,7 @@ pub fn analyzeContainer(mod: *Module, container_scope: *Scope.Container) !void { | ... | @@ -3310,7 +3481,7 @@ pub fn analyzeContainer(mod: *Module, container_scope: *Scope.Container) !void { |
| 3310 | .fn_proto_simple => { | 3481 | .fn_proto_simple => { |
| 3311 | var params: [1]ast.Node.Index = undefined; | 3482 | var params: [1]ast.Node.Index = undefined; |
| 3312 | try mod.semaContainerFn( | 3483 | try mod.semaContainerFn( |
| 3313 | container_scope, | 3484 | namespace, |
| 3314 | &deleted_decls, | 3485 | &deleted_decls, |
| 3315 | &outdated_decls, | 3486 | &outdated_decls, |
| 3316 | decl_node, | 3487 | decl_node, |
| ... | @@ -3320,7 +3491,7 @@ pub fn analyzeContainer(mod: *Module, container_scope: *Scope.Container) !void { | ... | @@ -3320,7 +3491,7 @@ pub fn analyzeContainer(mod: *Module, container_scope: *Scope.Container) !void { |
| 3320 | ); | 3491 | ); |
| 3321 | }, | 3492 | }, |
| 3322 | .fn_proto_multi => try mod.semaContainerFn( | 3493 | .fn_proto_multi => try mod.semaContainerFn( |
| 3323 | container_scope, | 3494 | namespace, |
| 3324 | &deleted_decls, | 3495 | &deleted_decls, |
| 3325 | &outdated_decls, | 3496 | &outdated_decls, |
| 3326 | decl_node, | 3497 | decl_node, |
| ... | @@ -3331,7 +3502,7 @@ pub fn analyzeContainer(mod: *Module, container_scope: *Scope.Container) !void { | ... | @@ -3331,7 +3502,7 @@ pub fn analyzeContainer(mod: *Module, container_scope: *Scope.Container) !void { |
| 3331 | .fn_proto_one => { | 3502 | .fn_proto_one => { |
| 3332 | var params: [1]ast.Node.Index = undefined; | 3503 | var params: [1]ast.Node.Index = undefined; |
| 3333 | try mod.semaContainerFn( | 3504 | try mod.semaContainerFn( |
| 3334 | container_scope, | 3505 | namespace, |
| 3335 | &deleted_decls, | 3506 | &deleted_decls, |
| 3336 | &outdated_decls, | 3507 | &outdated_decls, |
| 3337 | decl_node, | 3508 | decl_node, |
| ... | @@ -3341,7 +3512,7 @@ pub fn analyzeContainer(mod: *Module, container_scope: *Scope.Container) !void { | ... | @@ -3341,7 +3512,7 @@ pub fn analyzeContainer(mod: *Module, container_scope: *Scope.Container) !void { |
| 3341 | ); | 3512 | ); |
| 3342 | }, | 3513 | }, |
| 3343 | .fn_proto => try mod.semaContainerFn( | 3514 | .fn_proto => try mod.semaContainerFn( |
| 3344 | container_scope, | 3515 | namespace, |
| 3345 | &deleted_decls, | 3516 | &deleted_decls, |
| 3346 | &outdated_decls, | 3517 | &outdated_decls, |
| 3347 | decl_node, | 3518 | decl_node, |
| ... | @@ -3355,7 +3526,7 @@ pub fn analyzeContainer(mod: *Module, container_scope: *Scope.Container) !void { | ... | @@ -3355,7 +3526,7 @@ pub fn analyzeContainer(mod: *Module, container_scope: *Scope.Container) !void { |
| 3355 | .fn_proto_simple => { | 3526 | .fn_proto_simple => { |
| 3356 | var params: [1]ast.Node.Index = undefined; | 3527 | var params: [1]ast.Node.Index = undefined; |
| 3357 | try mod.semaContainerFn( | 3528 | try mod.semaContainerFn( |
| 3358 | container_scope, | 3529 | namespace, |
| 3359 | &deleted_decls, | 3530 | &deleted_decls, |
| 3360 | &outdated_decls, | 3531 | &outdated_decls, |
| 3361 | decl_node, | 3532 | decl_node, |
| ... | @@ -3365,7 +3536,7 @@ pub fn analyzeContainer(mod: *Module, container_scope: *Scope.Container) !void { | ... | @@ -3365,7 +3536,7 @@ pub fn analyzeContainer(mod: *Module, container_scope: *Scope.Container) !void { |
| 3365 | ); | 3536 | ); |
| 3366 | }, | 3537 | }, |
| 3367 | .fn_proto_multi => try mod.semaContainerFn( | 3538 | .fn_proto_multi => try mod.semaContainerFn( |
| 3368 | container_scope, | 3539 | namespace, |
| 3369 | &deleted_decls, | 3540 | &deleted_decls, |
| 3370 | &outdated_decls, | 3541 | &outdated_decls, |
| 3371 | decl_node, | 3542 | decl_node, |
| ... | @@ -3376,7 +3547,7 @@ pub fn analyzeContainer(mod: *Module, container_scope: *Scope.Container) !void { | ... | @@ -3376,7 +3547,7 @@ pub fn analyzeContainer(mod: *Module, container_scope: *Scope.Container) !void { |
| 3376 | .fn_proto_one => { | 3547 | .fn_proto_one => { |
| 3377 | var params: [1]ast.Node.Index = undefined; | 3548 | var params: [1]ast.Node.Index = undefined; |
| 3378 | try mod.semaContainerFn( | 3549 | try mod.semaContainerFn( |
| 3379 | container_scope, | 3550 | namespace, |
| 3380 | &deleted_decls, | 3551 | &deleted_decls, |
| 3381 | &outdated_decls, | 3552 | &outdated_decls, |
| 3382 | decl_node, | 3553 | decl_node, |
| ... | @@ -3386,7 +3557,7 @@ pub fn analyzeContainer(mod: *Module, container_scope: *Scope.Container) !void { | ... | @@ -3386,7 +3557,7 @@ pub fn analyzeContainer(mod: *Module, container_scope: *Scope.Container) !void { |
| 3386 | ); | 3557 | ); |
| 3387 | }, | 3558 | }, |
| 3388 | .fn_proto => try mod.semaContainerFn( | 3559 | .fn_proto => try mod.semaContainerFn( |
| 3389 | container_scope, | 3560 | namespace, |
| 3390 | &deleted_decls, | 3561 | &deleted_decls, |
| 3391 | &outdated_decls, | 3562 | &outdated_decls, |
| 3392 | decl_node, | 3563 | decl_node, |
| ... | @@ -3396,7 +3567,7 @@ pub fn analyzeContainer(mod: *Module, container_scope: *Scope.Container) !void { | ... | @@ -3396,7 +3567,7 @@ pub fn analyzeContainer(mod: *Module, container_scope: *Scope.Container) !void { |
| 3396 | ), | 3567 | ), |
| 3397 | | 3568 | |
| 3398 | .global_var_decl => try mod.semaContainerVar( | 3569 | .global_var_decl => try mod.semaContainerVar( |
| 3399 | container_scope, | 3570 | namespace, |
| 3400 | &deleted_decls, | 3571 | &deleted_decls, |
| 3401 | &outdated_decls, | 3572 | &outdated_decls, |
| 3402 | decl_node, | 3573 | decl_node, |
| ... | @@ -3404,7 +3575,7 @@ pub fn analyzeContainer(mod: *Module, container_scope: *Scope.Container) !void { | ... | @@ -3404,7 +3575,7 @@ pub fn analyzeContainer(mod: *Module, container_scope: *Scope.Container) !void { |
| 3404 | tree.globalVarDecl(decl_node), | 3575 | tree.globalVarDecl(decl_node), |
| 3405 | ), | 3576 | ), |
| 3406 | .local_var_decl => try mod.semaContainerVar( | 3577 | .local_var_decl => try mod.semaContainerVar( |
| 3407 | container_scope, | 3578 | namespace, |
| 3408 | &deleted_decls, | 3579 | &deleted_decls, |
| 3409 | &outdated_decls, | 3580 | &outdated_decls, |
| 3410 | decl_node, | 3581 | decl_node, |
| ... | @@ -3412,7 +3583,7 @@ pub fn analyzeContainer(mod: *Module, container_scope: *Scope.Container) !void { | ... | @@ -3412,7 +3583,7 @@ pub fn analyzeContainer(mod: *Module, container_scope: *Scope.Container) !void { |
| 3412 | tree.localVarDecl(decl_node), | 3583 | tree.localVarDecl(decl_node), |
| 3413 | ), | 3584 | ), |
| 3414 | .simple_var_decl => try mod.semaContainerVar( | 3585 | .simple_var_decl => try mod.semaContainerVar( |
| 3415 | container_scope, | 3586 | namespace, |
| 3416 | &deleted_decls, | 3587 | &deleted_decls, |
| 3417 | &outdated_decls, | 3588 | &outdated_decls, |
| 3418 | decl_node, | 3589 | decl_node, |
| ... | @@ -3420,7 +3591,7 @@ pub fn analyzeContainer(mod: *Module, container_scope: *Scope.Container) !void { | ... | @@ -3420,7 +3591,7 @@ pub fn analyzeContainer(mod: *Module, container_scope: *Scope.Container) !void { |
| 3420 | tree.simpleVarDecl(decl_node), | 3591 | tree.simpleVarDecl(decl_node), |
| 3421 | ), | 3592 | ), |
| 3422 | .aligned_var_decl => try mod.semaContainerVar( | 3593 | .aligned_var_decl => try mod.semaContainerVar( |
| 3423 | container_scope, | 3594 | namespace, |
| 3424 | &deleted_decls, | 3595 | &deleted_decls, |
| 3425 | &outdated_decls, | 3596 | &outdated_decls, |
| 3426 | decl_node, | 3597 | decl_node, |
| ... | @@ -3433,11 +3604,11 @@ pub fn analyzeContainer(mod: *Module, container_scope: *Scope.Container) !void { | ... | @@ -3433,11 +3604,11 @@ pub fn analyzeContainer(mod: *Module, container_scope: *Scope.Container) !void { |
| 3433 | const name = try std.fmt.allocPrint(mod.gpa, "__comptime_{d}", .{name_index}); | 3604 | const name = try std.fmt.allocPrint(mod.gpa, "__comptime_{d}", .{name_index}); |
| 3434 | defer mod.gpa.free(name); | 3605 | defer mod.gpa.free(name); |
| 3435 | | 3606 | |
| 3436 | const name_hash = container_scope.fullyQualifiedNameHash(name); | 3607 | const name_hash = namespace.fullyQualifiedNameHash(name); |
| 3437 | const contents_hash = std.zig.hashSrc(tree.getNodeSource(decl_node)); | 3608 | const contents_hash = std.zig.hashSrc(tree.getNodeSource(decl_node)); |
| 3438 | | 3609 | |
| 3439 | const new_decl = try mod.createNewDecl(&container_scope.base, name, decl_node, name_hash, contents_hash); | 3610 | const new_decl = try mod.createNewDecl(namespace, name, decl_node, name_hash, contents_hash); |
| 3440 | container_scope.decls.putAssumeCapacity(new_decl, {}); | 3611 | namespace.decls.putAssumeCapacity(new_decl, {}); |
| 3441 | mod.comp.work_queue.writeItemAssumeCapacity(.{ .analyze_decl = new_decl }); | 3612 | mod.comp.work_queue.writeItemAssumeCapacity(.{ .analyze_decl = new_decl }); |
| 3442 | }, | 3613 | }, |
| 3443 | | 3614 | |
| ... | @@ -3483,7 +3654,7 @@ pub fn analyzeContainer(mod: *Module, container_scope: *Scope.Container) !void { | ... | @@ -3483,7 +3654,7 @@ pub fn analyzeContainer(mod: *Module, container_scope: *Scope.Container) !void { |
| 3483 | | 3654 | |
| 3484 | fn semaContainerFn( | 3655 | fn semaContainerFn( |
| 3485 | mod: *Module, | 3656 | mod: *Module, |
| 3486 | container_scope: *Scope.Container, | 3657 | namespace: *Scope.Namespace, |
| 3487 | deleted_decls: *std.AutoArrayHashMap(*Decl, void), | 3658 | deleted_decls: *std.AutoArrayHashMap(*Decl, void), |
| 3488 | outdated_decls: *std.AutoArrayHashMap(*Decl, void), | 3659 | outdated_decls: *std.AutoArrayHashMap(*Decl, void), |
| 3489 | decl_node: ast.Node.Index, | 3660 | decl_node: ast.Node.Index, |
| ... | @@ -3500,25 +3671,25 @@ fn semaContainerFn( | ... | @@ -3500,25 +3671,25 @@ fn semaContainerFn( |
| 3500 | @panic("TODO missing function name"); | 3671 | @panic("TODO missing function name"); |
| 3501 | }; | 3672 | }; |
| 3502 | const name = tree.tokenSlice(name_token); // TODO use identifierTokenString | 3673 | const name = tree.tokenSlice(name_token); // TODO use identifierTokenString |
| 3503 | const name_hash = container_scope.fullyQualifiedNameHash(name); | 3674 | const name_hash = namespace.fullyQualifiedNameHash(name); |
| 3504 | const contents_hash = std.zig.hashSrc(tree.getNodeSource(decl_node)); | 3675 | const contents_hash = std.zig.hashSrc(tree.getNodeSource(decl_node)); |
| 3505 | if (mod.decl_table.get(name_hash)) |decl| { | 3676 | if (mod.decl_table.get(name_hash)) |decl| { |
| 3506 | // Update the AST Node index of the decl, even if its contents are unchanged, it may | 3677 | // Update the AST node of the decl; even if its contents are unchanged, it may |
| 3507 | // have been re-ordered. | 3678 | // have been re-ordered. |
| 3508 | const prev_src_node = decl.src_node; | 3679 | const prev_src_node = decl.src_node; |
| 3509 | decl.src_node = decl_node; | 3680 | decl.src_node = decl_node; |
| 3510 | if (deleted_decls.swapRemove(decl) == null) { | 3681 | if (deleted_decls.swapRemove(decl) == null) { |
| 3511 | decl.analysis = .sema_failure; | 3682 | decl.analysis = .sema_failure; |
| 3512 | const msg = try ErrorMsg.create(mod.gpa, .{ | 3683 | const msg = try ErrorMsg.create(mod.gpa, .{ |
| 3513 | .container = .{ .file_scope = container_scope.file_scope }, | 3684 | .container = .{ .file_scope = namespace.file_scope }, |
| 3514 | .lazy = .{ .token_abs = name_token }, | 3685 | .lazy = .{ .token_abs = name_token }, |
| 3515 | }, "redefinition of '{s}'", .{decl.name}); | 3686 | }, "redeclaration of '{s}'", .{decl.name}); |
| 3516 | errdefer msg.destroy(mod.gpa); | 3687 | errdefer msg.destroy(mod.gpa); |
| 3517 | const other_src_loc: SrcLoc = .{ | 3688 | const other_src_loc: SrcLoc = .{ |
| 3518 | .container = .{ .file_scope = decl.container.file_scope }, | 3689 | .container = .{ .file_scope = decl.namespace.file_scope }, |
| 3519 | .lazy = .{ .node_abs = prev_src_node }, | 3690 | .lazy = .{ .node_abs = prev_src_node }, |
| 3520 | }; | 3691 | }; |
| 3521 | try mod.errNoteNonLazy(other_src_loc, msg, "previous definition here", .{}); | 3692 | try mod.errNoteNonLazy(other_src_loc, msg, "previously declared here", .{}); |
| 3522 | try mod.failed_decls.putNoClobber(mod.gpa, decl, msg); | 3693 | try mod.failed_decls.putNoClobber(mod.gpa, decl, msg); |
| 3523 | } else { | 3694 | } else { |
| 3524 | if (!srcHashEql(decl.contents_hash, contents_hash)) { | 3695 | if (!srcHashEql(decl.contents_hash, contents_hash)) { |
| ... | @@ -3542,8 +3713,8 @@ fn semaContainerFn( | ... | @@ -3542,8 +3713,8 @@ fn semaContainerFn( |
| 3542 | } | 3713 | } |
| 3543 | } | 3714 | } |
| 3544 | } else { | 3715 | } else { |
| 3545 | const new_decl = try mod.createNewDecl(&container_scope.base, name, decl_node, name_hash, contents_hash); | 3716 | const new_decl = try mod.createNewDecl(namespace, name, decl_node, name_hash, contents_hash); |
| 3546 | container_scope.decls.putAssumeCapacity(new_decl, {}); | 3717 | namespace.decls.putAssumeCapacity(new_decl, {}); |
| 3547 | if (fn_proto.extern_export_token) |maybe_export_token| { | 3718 | if (fn_proto.extern_export_token) |maybe_export_token| { |
| 3548 | const token_tags = tree.tokens.items(.tag); | 3719 | const token_tags = tree.tokens.items(.tag); |
| 3549 | if (token_tags[maybe_export_token] == .keyword_export) { | 3720 | if (token_tags[maybe_export_token] == .keyword_export) { |
| ... | @@ -3556,7 +3727,7 @@ fn semaContainerFn( | ... | @@ -3556,7 +3727,7 @@ fn semaContainerFn( |
| 3556 | | 3727 | |
| 3557 | fn semaContainerVar( | 3728 | fn semaContainerVar( |
| 3558 | mod: *Module, | 3729 | mod: *Module, |
| 3559 | container_scope: *Scope.Container, | 3730 | namespace: *Scope.Namespace, |
| 3560 | deleted_decls: *std.AutoArrayHashMap(*Decl, void), | 3731 | deleted_decls: *std.AutoArrayHashMap(*Decl, void), |
| 3561 | outdated_decls: *std.AutoArrayHashMap(*Decl, void), | 3732 | outdated_decls: *std.AutoArrayHashMap(*Decl, void), |
| 3562 | decl_node: ast.Node.Index, | 3733 | decl_node: ast.Node.Index, |
| ... | @@ -3568,7 +3739,7 @@ fn semaContainerVar( | ... | @@ -3568,7 +3739,7 @@ fn semaContainerVar( |
| 3568 | | 3739 | |
| 3569 | const name_token = var_decl.ast.mut_token + 1; | 3740 | const name_token = var_decl.ast.mut_token + 1; |
| 3570 | const name = tree.tokenSlice(name_token); // TODO identifierTokenString | 3741 | const name = tree.tokenSlice(name_token); // TODO identifierTokenString |
| 3571 | const name_hash = container_scope.fullyQualifiedNameHash(name); | 3742 | const name_hash = namespace.fullyQualifiedNameHash(name); |
| 3572 | const contents_hash = std.zig.hashSrc(tree.getNodeSource(decl_node)); | 3743 | const contents_hash = std.zig.hashSrc(tree.getNodeSource(decl_node)); |
| 3573 | if (mod.decl_table.get(name_hash)) |decl| { | 3744 | if (mod.decl_table.get(name_hash)) |decl| { |
| 3574 | // Update the AST Node index of the decl, even if its contents are unchanged, it may | 3745 | // Update the AST Node index of the decl, even if its contents are unchanged, it may |
| ... | @@ -3578,23 +3749,23 @@ fn semaContainerVar( | ... | @@ -3578,23 +3749,23 @@ fn semaContainerVar( |
| 3578 | if (deleted_decls.swapRemove(decl) == null) { | 3749 | if (deleted_decls.swapRemove(decl) == null) { |
| 3579 | decl.analysis = .sema_failure; | 3750 | decl.analysis = .sema_failure; |
| 3580 | const msg = try ErrorMsg.create(mod.gpa, .{ | 3751 | const msg = try ErrorMsg.create(mod.gpa, .{ |
| 3581 | .container = .{ .file_scope = container_scope.file_scope }, | 3752 | .container = .{ .file_scope = namespace.file_scope }, |
| 3582 | .lazy = .{ .token_abs = name_token }, | 3753 | .lazy = .{ .token_abs = name_token }, |
| 3583 | }, "redefinition of '{s}'", .{decl.name}); | 3754 | }, "redeclaration of '{s}'", .{decl.name}); |
| 3584 | errdefer msg.destroy(mod.gpa); | 3755 | errdefer msg.destroy(mod.gpa); |
| 3585 | const other_src_loc: SrcLoc = .{ | 3756 | const other_src_loc: SrcLoc = .{ |
| 3586 | .container = .{ .file_scope = decl.container.file_scope }, | 3757 | .container = .{ .file_scope = decl.namespace.file_scope }, |
| 3587 | .lazy = .{ .node_abs = prev_src_node }, | 3758 | .lazy = .{ .node_abs = prev_src_node }, |
| 3588 | }; | 3759 | }; |
| 3589 | try mod.errNoteNonLazy(other_src_loc, msg, "previous definition here", .{}); | 3760 | try mod.errNoteNonLazy(other_src_loc, msg, "previously declared here", .{}); |
| 3590 | try mod.failed_decls.putNoClobber(mod.gpa, decl, msg); | 3761 | try mod.failed_decls.putNoClobber(mod.gpa, decl, msg); |
| 3591 | } else if (!srcHashEql(decl.contents_hash, contents_hash)) { | 3762 | } else if (!srcHashEql(decl.contents_hash, contents_hash)) { |
| 3592 | try outdated_decls.put(decl, {}); | 3763 | try outdated_decls.put(decl, {}); |
| 3593 | decl.contents_hash = contents_hash; | 3764 | decl.contents_hash = contents_hash; |
| 3594 | } | 3765 | } |
| 3595 | } else { | 3766 | } else { |
| 3596 | const new_decl = try mod.createNewDecl(&container_scope.base, name, decl_node, name_hash, contents_hash); | 3767 | const new_decl = try mod.createNewDecl(namespace, name, decl_node, name_hash, contents_hash); |
| 3597 | container_scope.decls.putAssumeCapacity(new_decl, {}); | 3768 | namespace.decls.putAssumeCapacity(new_decl, {}); |
| 3598 | if (var_decl.extern_export_token) |maybe_export_token| { | 3769 | if (var_decl.extern_export_token) |maybe_export_token| { |
| 3599 | const token_tags = tree.tokens.items(.tag); | 3770 | const token_tags = tree.tokens.items(.tag); |
| 3600 | if (token_tags[maybe_export_token] == .keyword_export) { | 3771 | if (token_tags[maybe_export_token] == .keyword_export) { |
| ... | @@ -3624,7 +3795,7 @@ pub fn deleteDecl( | ... | @@ -3624,7 +3795,7 @@ pub fn deleteDecl( |
| 3624 | | 3795 | |
| 3625 | // Remove from the namespace it resides in. In the case of an anonymous Decl it will | 3796 | // Remove from the namespace it resides in. In the case of an anonymous Decl it will |
| 3626 | // not be present in the set, and this does nothing. | 3797 | // not be present in the set, and this does nothing. |
| 3627 | decl.container.removeDecl(decl); | 3798 | decl.namespace.removeDecl(decl); |
| 3628 | | 3799 | |
| 3629 | const name_hash = decl.fullyQualifiedNameHash(); | 3800 | const name_hash = decl.fullyQualifiedNameHash(); |
| 3630 | mod.decl_table.removeAssertDiscard(name_hash); | 3801 | mod.decl_table.removeAssertDiscard(name_hash); |
| ... | @@ -3786,7 +3957,7 @@ fn markOutdatedDecl(mod: *Module, decl: *Decl) !void { | ... | @@ -3786,7 +3957,7 @@ fn markOutdatedDecl(mod: *Module, decl: *Decl) !void { |
| 3786 | | 3957 | |
| 3787 | fn allocateNewDecl( | 3958 | fn allocateNewDecl( |
| 3788 | mod: *Module, | 3959 | mod: *Module, |
| 3789 | scope: *Scope, | 3960 | namespace: *Scope.Namespace, |
| 3790 | src_node: ast.Node.Index, | 3961 | src_node: ast.Node.Index, |
| 3791 | contents_hash: std.zig.SrcHash, | 3962 | contents_hash: std.zig.SrcHash, |
| 3792 | ) !*Decl { | 3963 | ) !*Decl { |
| ... | @@ -3802,7 +3973,7 @@ fn allocateNewDecl( | ... | @@ -3802,7 +3973,7 @@ fn allocateNewDecl( |
| 3802 | | 3973 | |
| 3803 | new_decl.* = .{ | 3974 | new_decl.* = .{ |
| 3804 | .name = "", | 3975 | .name = "", |
| 3805 | .container = scope.namespace(), | 3976 | .namespace = namespace, |
| 3806 | .src_node = src_node, | 3977 | .src_node = src_node, |
| 3807 | .typed_value = .{ .never_succeeded = {} }, | 3978 | .typed_value = .{ .never_succeeded = {} }, |
| 3808 | .analysis = .unreferenced, | 3979 | .analysis = .unreferenced, |
| ... | @@ -3832,14 +4003,14 @@ fn allocateNewDecl( | ... | @@ -3832,14 +4003,14 @@ fn allocateNewDecl( |
| 3832 | | 4003 | |
| 3833 | fn createNewDecl( | 4004 | fn createNewDecl( |
| 3834 | mod: *Module, | 4005 | mod: *Module, |
| 3835 | scope: *Scope, | 4006 | namespace: *Scope.Namespace, |
| 3836 | decl_name: []const u8, | 4007 | decl_name: []const u8, |
| 3837 | src_node: ast.Node.Index, | 4008 | src_node: ast.Node.Index, |
| 3838 | name_hash: Scope.NameHash, | 4009 | name_hash: Scope.NameHash, |
| 3839 | contents_hash: std.zig.SrcHash, | 4010 | contents_hash: std.zig.SrcHash, |
| 3840 | ) !*Decl { | 4011 | ) !*Decl { |
| 3841 | try mod.decl_table.ensureCapacity(mod.gpa, mod.decl_table.items().len + 1); | 4012 | try mod.decl_table.ensureCapacity(mod.gpa, mod.decl_table.items().len + 1); |
| 3842 | const new_decl = try mod.allocateNewDecl(scope, src_node, contents_hash); | 4013 | const new_decl = try mod.allocateNewDecl(namespace, src_node, contents_hash); |
| 3843 | errdefer mod.gpa.destroy(new_decl); | 4014 | errdefer mod.gpa.destroy(new_decl); |
| 3844 | new_decl.name = try mem.dupeZ(mod.gpa, u8, decl_name); | 4015 | new_decl.name = try mem.dupeZ(mod.gpa, u8, decl_name); |
| 3845 | mod.decl_table.putAssumeCapacityNoClobber(name_hash, new_decl); | 4016 | mod.decl_table.putAssumeCapacityNoClobber(name_hash, new_decl); |
| ... | @@ -3930,7 +4101,7 @@ pub fn analyzeExport( | ... | @@ -3930,7 +4101,7 @@ pub fn analyzeExport( |
| 3930 | ); | 4101 | ); |
| 3931 | errdefer msg.destroy(mod.gpa); | 4102 | errdefer msg.destroy(mod.gpa); |
| 3932 | try mod.errNote( | 4103 | try mod.errNote( |
| 3933 | &other_export.owner_decl.container.base, | 4104 | &other_export.owner_decl.namespace.base, |
| 3934 | other_export.src, | 4105 | other_export.src, |
| 3935 | msg, | 4106 | msg, |
| 3936 | "other symbol here", | 4107 | "other symbol here", |
| ... | @@ -4050,9 +4221,10 @@ pub fn createAnonymousDecl( | ... | @@ -4050,9 +4221,10 @@ pub fn createAnonymousDecl( |
| 4050 | const scope_decl = scope.ownerDecl().?; | 4221 | const scope_decl = scope.ownerDecl().?; |
| 4051 | const name = try std.fmt.allocPrint(mod.gpa, "{s}__anon_{d}", .{ scope_decl.name, name_index }); | 4222 | const name = try std.fmt.allocPrint(mod.gpa, "{s}__anon_{d}", .{ scope_decl.name, name_index }); |
| 4052 | defer mod.gpa.free(name); | 4223 | defer mod.gpa.free(name); |
| 4053 | const name_hash = scope.namespace().fullyQualifiedNameHash(name); | 4224 | const namespace = scope_decl.namespace; |
| | 4225 | const name_hash = namespace.fullyQualifiedNameHash(name); |
| 4054 | const src_hash: std.zig.SrcHash = undefined; | 4226 | const src_hash: std.zig.SrcHash = undefined; |
| 4055 | const new_decl = try mod.createNewDecl(scope, name, scope_decl.src_node, name_hash, src_hash); | 4227 | const new_decl = try mod.createNewDecl(namespace, name, scope_decl.src_node, name_hash, src_hash); |
| 4056 | const decl_arena_state = try decl_arena.allocator.create(std.heap.ArenaAllocator.State); | 4228 | const decl_arena_state = try decl_arena.allocator.create(std.heap.ArenaAllocator.State); |
| 4057 | | 4229 | |
| 4058 | decl_arena_state.* = decl_arena.state; | 4230 | decl_arena_state.* = decl_arena.state; |
| ... | @@ -4076,55 +4248,30 @@ pub fn createAnonymousDecl( | ... | @@ -4076,55 +4248,30 @@ pub fn createAnonymousDecl( |
| 4076 | return new_decl; | 4248 | return new_decl; |
| 4077 | } | 4249 | } |
| 4078 | | 4250 | |
| 4079 | pub fn createContainerDecl( | | |
| 4080 | mod: *Module, | | |
| 4081 | scope: *Scope, | | |
| 4082 | base_token: std.zig.ast.TokenIndex, | | |
| 4083 | decl_arena: *std.heap.ArenaAllocator, | | |
| 4084 | typed_value: TypedValue, | | |
| 4085 | ) !*Decl { | | |
| 4086 | const scope_decl = scope.ownerDecl().?; | | |
| 4087 | const name = try mod.getAnonTypeName(scope, base_token); | | |
| 4088 | defer mod.gpa.free(name); | | |
| 4089 | const name_hash = scope.namespace().fullyQualifiedNameHash(name); | | |
| 4090 | const src_hash: std.zig.SrcHash = undefined; | | |
| 4091 | const new_decl = try mod.createNewDecl(scope, name, scope_decl.src_node, name_hash, src_hash); | | |
| 4092 | const decl_arena_state = try decl_arena.allocator.create(std.heap.ArenaAllocator.State); | | |
| 4093 | | | |
| 4094 | decl_arena_state.* = decl_arena.state; | | |
| 4095 | new_decl.typed_value = .{ | | |
| 4096 | .most_recent = .{ | | |
| 4097 | .typed_value = typed_value, | | |
| 4098 | .arena = decl_arena_state, | | |
| 4099 | }, | | |
| 4100 | }; | | |
| 4101 | new_decl.analysis = .complete; | | |
| 4102 | new_decl.generation = mod.generation; | | |
| 4103 | | | |
| 4104 | return new_decl; | | |
| 4105 | } | | |
| 4106 | | | |
| 4107 | fn getAnonTypeName(mod: *Module, scope: *Scope, base_token: std.zig.ast.TokenIndex) ![]u8 { | | |
| 4108 | // TODO add namespaces, generic function signatrues | | |
| 4109 | const tree = scope.tree(); | | |
| 4110 | const token_tags = tree.tokens.items(.tag); | | |
| 4111 | const base_name = switch (token_tags[base_token]) { | | |
| 4112 | .keyword_struct => "struct", | | |
| 4113 | .keyword_enum => "enum", | | |
| 4114 | .keyword_union => "union", | | |
| 4115 | .keyword_opaque => "opaque", | | |
| 4116 | else => unreachable, | | |
| 4117 | }; | | |
| 4118 | const loc = tree.tokenLocation(0, base_token); | | |
| 4119 | return std.fmt.allocPrint(mod.gpa, "{s}:{d}:{d}", .{ base_name, loc.line, loc.column }); | | |
| 4120 | } | | |
| 4121 | | | |
| 4122 | fn getNextAnonNameIndex(mod: *Module) usize { | 4251 | fn getNextAnonNameIndex(mod: *Module) usize { |
| 4123 | return @atomicRmw(usize, &mod.next_anon_name_index, .Add, 1, .Monotonic); | 4252 | return @atomicRmw(usize, &mod.next_anon_name_index, .Add, 1, .Monotonic); |
| 4124 | } | 4253 | } |
| 4125 | | 4254 | |
| 4126 | pub fn lookupDeclName(mod: *Module, scope: *Scope, ident_name: []const u8) ?*Decl { | 4255 | /// This looks up a bare identifier in the given scope. This will walk up the tree of namespaces |
| 4127 | const namespace = scope.namespace(); | 4256 | /// in scope and check each one for the identifier. |
| | 4257 | pub fn lookupIdentifier(mod: *Module, scope: *Scope, ident_name: []const u8) ?*Decl { |
| | 4258 | var namespace = scope.namespace(); |
| | 4259 | while (true) { |
| | 4260 | if (mod.lookupInNamespace(namespace, ident_name)) |decl| { |
| | 4261 | return decl; |
| | 4262 | } |
| | 4263 | namespace = namespace.parent orelse break; |
| | 4264 | } |
| | 4265 | return null; |
| | 4266 | } |
| | 4267 | |
| | 4268 | /// This looks up a member of a specific namespace. It is affected by `usingnamespace` but |
| | 4269 | /// only for ones in the specified namespace. |
| | 4270 | pub fn lookupInNamespace( |
| | 4271 | mod: *Module, |
| | 4272 | namespace: *Scope.Namespace, |
| | 4273 | ident_name: []const u8, |
| | 4274 | ) ?*Decl { |
| 4128 | const name_hash = namespace.fullyQualifiedNameHash(ident_name); | 4275 | const name_hash = namespace.fullyQualifiedNameHash(ident_name); |
| 4129 | return mod.decl_table.get(name_hash); | 4276 | return mod.decl_table.get(name_hash); |
| 4130 | } | 4277 | } |
| ... | @@ -4271,7 +4418,7 @@ pub fn failWithOwnedErrorMsg(mod: *Module, scope: *Scope, err_msg: *ErrorMsg) In | ... | @@ -4271,7 +4418,7 @@ pub fn failWithOwnedErrorMsg(mod: *Module, scope: *Scope, err_msg: *ErrorMsg) In |
| 4271 | mod.failed_decls.putAssumeCapacityNoClobber(gen_zir.astgen.decl, err_msg); | 4418 | mod.failed_decls.putAssumeCapacityNoClobber(gen_zir.astgen.decl, err_msg); |
| 4272 | }, | 4419 | }, |
| 4273 | .file => unreachable, | 4420 | .file => unreachable, |
| 4274 | .container => unreachable, | 4421 | .namespace => unreachable, |
| 4275 | .decl_ref => { | 4422 | .decl_ref => { |
| 4276 | const decl_ref = scope.cast(Scope.DeclRef).?; | 4423 | const decl_ref = scope.cast(Scope.DeclRef).?; |
| 4277 | decl_ref.decl.analysis = .sema_failure; | 4424 | decl_ref.decl.analysis = .sema_failure; |
| ... | @@ -4683,10 +4830,3 @@ pub fn parseStrLit( | ... | @@ -4683,10 +4830,3 @@ pub fn parseStrLit( |
| 4683 | }, | 4830 | }, |
| 4684 | } | 4831 | } |
| 4685 | } | 4832 | } |
| 4686 | | | |
| 4687 | pub fn unloadFile(mod: *Module, file_scope: *Scope.File) void { | | |
| 4688 | if (file_scope.status == .unloaded_parse_failure) { | | |
| 4689 | mod.failed_files.swapRemove(file_scope).?.value.destroy(mod.gpa); | | |
| 4690 | } | | |
| 4691 | file_scope.unload(mod.gpa); | | |
| 4692 | } | | |