mirror of
https://github.com/ziglang/zig.git
synced 2026-02-12 20:37:54 +00:00
stage2: fully qualified names and better anonymous names
* no more global atomic variable for anonymous decl indexes. Instead
the Namespace decl table is used to figure out anonymous decl names.
- This prepares for better multi-threaded semantic analysis in the
future, with no contention on this global atomic integer.
* implement fully qualified names for namespaces.
This commit is contained in:
parent
aa0352fad6
commit
5cd9afc6b6
@ -75,8 +75,6 @@ failed_files: std.AutoArrayHashMapUnmanaged(*Scope.File, ?*ErrorMsg) = .{},
|
||||
/// The ErrorMsg memory is owned by the `Export`, using Module's general purpose allocator.
|
||||
failed_exports: std.AutoArrayHashMapUnmanaged(*Export, *ErrorMsg) = .{},
|
||||
|
||||
next_anon_name_index: usize = 0,
|
||||
|
||||
/// Candidates for deletion. After a semantic analysis update completes, this list
|
||||
/// contains Decls that need to be deleted if they end up having no references to them.
|
||||
deletion_set: std.AutoArrayHashMapUnmanaged(*Decl, void) = .{},
|
||||
@ -912,9 +910,22 @@ pub const Scope = struct {
|
||||
_ = ns.decls.orderedRemove(mem.spanZ(child.name));
|
||||
}
|
||||
|
||||
pub fn renderFullyQualifiedName(ns: Namespace, name: []const u8, writer: anytype) !void {
|
||||
// TODO this should render e.g. "std.fs.Dir.OpenOptions"
|
||||
return writer.writeAll(name);
|
||||
// This renders e.g. "std.fs.Dir.OpenOptions"
|
||||
pub fn renderFullyQualifiedName(
|
||||
ns: Namespace,
|
||||
name: []const u8,
|
||||
writer: anytype,
|
||||
) @TypeOf(writer).Error!void {
|
||||
if (ns.parent) |parent| {
|
||||
const decl = ns.getDecl();
|
||||
try parent.renderFullyQualifiedName(mem.spanZ(decl.name), writer);
|
||||
} else {
|
||||
try ns.file_scope.renderFullyQualifiedName(writer);
|
||||
}
|
||||
if (name.len != 0) {
|
||||
try writer.writeAll(".");
|
||||
try writer.writeAll(name);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn getDecl(ns: Namespace) *Decl {
|
||||
@ -1054,16 +1065,21 @@ pub const Scope = struct {
|
||||
gpa.destroy(file);
|
||||
}
|
||||
|
||||
pub fn fullyQualifiedNameZ(file: File, gpa: *Allocator) ![:0]u8 {
|
||||
pub fn renderFullyQualifiedName(file: File, writer: anytype) !void {
|
||||
// Convert all the slashes into dots and truncate the extension.
|
||||
const ext = std.fs.path.extension(file.sub_file_path);
|
||||
const noext = file.sub_file_path[0 .. file.sub_file_path.len - ext.len];
|
||||
const duped = try gpa.dupeZ(u8, noext);
|
||||
for (duped) |*byte| switch (byte.*) {
|
||||
'/', '\\' => byte.* = '.',
|
||||
else => continue,
|
||||
for (noext) |byte| switch (byte) {
|
||||
'/', '\\' => try writer.writeByte('.'),
|
||||
else => try writer.writeByte(byte),
|
||||
};
|
||||
return duped;
|
||||
}
|
||||
|
||||
pub fn fullyQualifiedNameZ(file: File, gpa: *Allocator) ![:0]u8 {
|
||||
var buf = std.ArrayList(u8).init(gpa);
|
||||
defer buf.deinit();
|
||||
try file.renderFullyQualifiedName(buf.writer());
|
||||
return buf.toOwnedSliceSentinel(0);
|
||||
}
|
||||
|
||||
pub fn dumpSrc(file: *File, src: LazySrcLoc) void {
|
||||
@ -3723,17 +3739,34 @@ pub fn constIntBig(mod: *Module, arena: *Allocator, src: LazySrcLoc, ty: Type, b
|
||||
}
|
||||
|
||||
pub fn createAnonymousDecl(mod: *Module, scope: *Scope, typed_value: TypedValue) !*Decl {
|
||||
const name_index = mod.getNextAnonNameIndex();
|
||||
const scope_decl = scope.ownerDecl().?;
|
||||
const namespace = scope_decl.namespace;
|
||||
try namespace.decls.ensureCapacity(mod.gpa, namespace.decls.count() + 1);
|
||||
const name = try std.fmt.allocPrintZ(mod.gpa, "{s}__anon_{d}", .{ scope_decl.name, name_index });
|
||||
errdefer mod.gpa.free(name);
|
||||
const new_decl = try mod.allocateNewDecl(namespace, scope_decl.src_node);
|
||||
namespace.decls.putAssumeCapacityNoClobber(name, new_decl);
|
||||
try namespace.decls.ensureUnusedCapacity(mod.gpa, 1);
|
||||
|
||||
// Find a unique name for the anon decl.
|
||||
var name_buf = std.ArrayList(u8).init(mod.gpa);
|
||||
defer name_buf.deinit();
|
||||
|
||||
try name_buf.appendSlice(mem.spanZ(scope_decl.name));
|
||||
var name_index: usize = namespace.decls.count();
|
||||
|
||||
const new_decl = while (true) {
|
||||
const gop = namespace.decls.getOrPutAssumeCapacity(name_buf.items);
|
||||
if (!gop.found_existing) {
|
||||
const name = try name_buf.toOwnedSliceSentinel(0);
|
||||
const new_decl = try mod.allocateNewDecl(namespace, scope_decl.src_node);
|
||||
new_decl.name = name;
|
||||
gop.entry.key = name;
|
||||
gop.entry.value = new_decl;
|
||||
break gop.entry.value;
|
||||
}
|
||||
|
||||
name_buf.clearRetainingCapacity();
|
||||
try name_buf.writer().print("{s}__anon_{d}", .{ scope_decl.name, name_index });
|
||||
name_index += 1;
|
||||
} else unreachable; // TODO should not need else unreachable on while(true)
|
||||
|
||||
new_decl.src_line = scope_decl.src_line;
|
||||
new_decl.name = name;
|
||||
new_decl.ty = typed_value.ty;
|
||||
new_decl.val = typed_value.val;
|
||||
new_decl.has_tv = true;
|
||||
@ -3751,10 +3784,6 @@ pub fn createAnonymousDecl(mod: *Module, scope: *Scope, typed_value: TypedValue)
|
||||
return new_decl;
|
||||
}
|
||||
|
||||
fn getNextAnonNameIndex(mod: *Module) usize {
|
||||
return @atomicRmw(usize, &mod.next_anon_name_index, .Add, 1, .Monotonic);
|
||||
}
|
||||
|
||||
/// This looks up a bare identifier in the given scope. This will walk up the tree of namespaces
|
||||
/// in scope and check each one for the identifier.
|
||||
/// TODO emit a compile error if more than one decl would be matched.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user