| ... | ... | @@ -75,8 +75,6 @@ failed_files: std.AutoArrayHashMapUnmanaged(*Scope.File, ?*ErrorMsg) = .{}, |
| 75 | 75 | /// The ErrorMsg memory is owned by the `Export`, using Module's general purpose allocator. |
| 76 | 76 | failed_exports: std.AutoArrayHashMapUnmanaged(*Export, *ErrorMsg) = .{}, |
| 77 | 77 | |
| 78 | | next_anon_name_index: usize = 0, |
| 79 | | |
| 80 | 78 | /// Candidates for deletion. After a semantic analysis update completes, this list |
| 81 | 79 | /// contains Decls that need to be deleted if they end up having no references to them. |
| 82 | 80 | deletion_set: std.AutoArrayHashMapUnmanaged(*Decl, void) = .{}, |
| ... | ... | @@ -912,9 +910,22 @@ pub const Scope = struct { |
| 912 | 910 | _ = ns.decls.orderedRemove(mem.spanZ(child.name)); |
| 913 | 911 | } |
| 914 | 912 | |
| 915 | | pub fn renderFullyQualifiedName(ns: Namespace, name: []const u8, writer: anytype) !void { |
| 916 | | // TODO this should render e.g. "std.fs.Dir.OpenOptions" |
| 917 | | return writer.writeAll(name); |
| 913 | // This renders e.g. "std.fs.Dir.OpenOptions" |
| 914 | pub fn renderFullyQualifiedName( |
| 915 | ns: Namespace, |
| 916 | name: []const u8, |
| 917 | writer: anytype, |
| 918 | ) @TypeOf(writer).Error!void { |
| 919 | if (ns.parent) |parent| { |
| 920 | const decl = ns.getDecl(); |
| 921 | try parent.renderFullyQualifiedName(mem.spanZ(decl.name), writer); |
| 922 | } else { |
| 923 | try ns.file_scope.renderFullyQualifiedName(writer); |
| 924 | } |
| 925 | if (name.len != 0) { |
| 926 | try writer.writeAll("."); |
| 927 | try writer.writeAll(name); |
| 928 | } |
| 918 | 929 | } |
| 919 | 930 | |
| 920 | 931 | pub fn getDecl(ns: Namespace) *Decl { |
| ... | ... | @@ -1054,16 +1065,21 @@ pub const Scope = struct { |
| 1054 | 1065 | gpa.destroy(file); |
| 1055 | 1066 | } |
| 1056 | 1067 | |
| 1057 | | pub fn fullyQualifiedNameZ(file: File, gpa: *Allocator) ![:0]u8 { |
| 1068 | pub fn renderFullyQualifiedName(file: File, writer: anytype) !void { |
| 1058 | 1069 | // Convert all the slashes into dots and truncate the extension. |
| 1059 | 1070 | const ext = std.fs.path.extension(file.sub_file_path); |
| 1060 | 1071 | const noext = file.sub_file_path[0 .. file.sub_file_path.len - ext.len]; |
| 1061 | | const duped = try gpa.dupeZ(u8, noext); |
| 1062 | | for (duped) |*byte| switch (byte.*) { |
| 1063 | | '/', '\\' => byte.* = '.', |
| 1064 | | else => continue, |
| 1072 | for (noext) |byte| switch (byte) { |
| 1073 | '/', '\\' => try writer.writeByte('.'), |
| 1074 | else => try writer.writeByte(byte), |
| 1065 | 1075 | }; |
| 1066 | | return duped; |
| 1076 | } |
| 1077 | |
| 1078 | pub fn fullyQualifiedNameZ(file: File, gpa: *Allocator) ![:0]u8 { |
| 1079 | var buf = std.ArrayList(u8).init(gpa); |
| 1080 | defer buf.deinit(); |
| 1081 | try file.renderFullyQualifiedName(buf.writer()); |
| 1082 | return buf.toOwnedSliceSentinel(0); |
| 1067 | 1083 | } |
| 1068 | 1084 | |
| 1069 | 1085 | pub fn dumpSrc(file: *File, src: LazySrcLoc) void { |
| ... | ... | @@ -3723,17 +3739,34 @@ pub fn constIntBig(mod: *Module, arena: *Allocator, src: LazySrcLoc, ty: Type, b |
| 3723 | 3739 | } |
| 3724 | 3740 | |
| 3725 | 3741 | pub fn createAnonymousDecl(mod: *Module, scope: *Scope, typed_value: TypedValue) !*Decl { |
| 3726 | | const name_index = mod.getNextAnonNameIndex(); |
| 3727 | 3742 | const scope_decl = scope.ownerDecl().?; |
| 3728 | 3743 | const namespace = scope_decl.namespace; |
| 3729 | | try namespace.decls.ensureCapacity(mod.gpa, namespace.decls.count() + 1); |
| 3730 | | const name = try std.fmt.allocPrintZ(mod.gpa, "{s}__anon_{d}", .{ scope_decl.name, name_index }); |
| 3731 | | errdefer mod.gpa.free(name); |
| 3732 | | const new_decl = try mod.allocateNewDecl(namespace, scope_decl.src_node); |
| 3733 | | namespace.decls.putAssumeCapacityNoClobber(name, new_decl); |
| 3744 | try namespace.decls.ensureUnusedCapacity(mod.gpa, 1); |
| 3745 | |
| 3746 | // Find a unique name for the anon decl. |
| 3747 | var name_buf = std.ArrayList(u8).init(mod.gpa); |
| 3748 | defer name_buf.deinit(); |
| 3749 | |
| 3750 | try name_buf.appendSlice(mem.spanZ(scope_decl.name)); |
| 3751 | var name_index: usize = namespace.decls.count(); |
| 3752 | |
| 3753 | const new_decl = while (true) { |
| 3754 | const gop = namespace.decls.getOrPutAssumeCapacity(name_buf.items); |
| 3755 | if (!gop.found_existing) { |
| 3756 | const name = try name_buf.toOwnedSliceSentinel(0); |
| 3757 | const new_decl = try mod.allocateNewDecl(namespace, scope_decl.src_node); |
| 3758 | new_decl.name = name; |
| 3759 | gop.entry.key = name; |
| 3760 | gop.entry.value = new_decl; |
| 3761 | break gop.entry.value; |
| 3762 | } |
| 3763 | |
| 3764 | name_buf.clearRetainingCapacity(); |
| 3765 | try name_buf.writer().print("{s}__anon_{d}", .{ scope_decl.name, name_index }); |
| 3766 | name_index += 1; |
| 3767 | } else unreachable; // TODO should not need else unreachable on while(true) |
| 3734 | 3768 | |
| 3735 | 3769 | new_decl.src_line = scope_decl.src_line; |
| 3736 | | new_decl.name = name; |
| 3737 | 3770 | new_decl.ty = typed_value.ty; |
| 3738 | 3771 | new_decl.val = typed_value.val; |
| 3739 | 3772 | new_decl.has_tv = true; |
| ... | ... | @@ -3751,10 +3784,6 @@ pub fn createAnonymousDecl(mod: *Module, scope: *Scope, typed_value: TypedValue) |
| 3751 | 3784 | return new_decl; |
| 3752 | 3785 | } |
| 3753 | 3786 | |
| 3754 | | fn getNextAnonNameIndex(mod: *Module) usize { |
| 3755 | | return @atomicRmw(usize, &mod.next_anon_name_index, .Add, 1, .Monotonic); |
| 3756 | | } |
| 3757 | | |
| 3758 | 3787 | /// This looks up a bare identifier in the given scope. This will walk up the tree of namespaces |
| 3759 | 3788 | /// in scope and check each one for the identifier. |
| 3760 | 3789 | /// TODO emit a compile error if more than one decl would be matched. |