Commit 6d3858dc8a

Vexu <git@vexu.eu>
2020-09-30 17:02:00
stage2: use directory handles for imports
1 parent d819da4
src/Compilation.zig
@@ -8,6 +8,7 @@ const log = std.log.scoped(.compilation);
 const Target = std.Target;
 
 const Value = @import("value.zig").Value;
+const Type = @import("type.zig").Type;
 const target_util = @import("target.zig");
 const Package = @import("Package.zig");
 const link = @import("link.zig");
@@ -638,15 +639,19 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
 
             const root_scope = rs: {
                 if (mem.endsWith(u8, root_pkg.root_src_path, ".zig")) {
+                    const struct_payload = try gpa.create(Type.Payload.EmptyStruct);
                     const root_scope = try gpa.create(Module.Scope.File);
+                    struct_payload.* = .{ .scope = &root_scope.root_container };
                     root_scope.* = .{
-                        .sub_file_path = root_pkg.root_src_path,
+                        // TODO this is duped so it can be freed in Container.deinit
+                        .sub_file_path = try gpa.dupe(u8, root_pkg.root_src_path),
                         .source = .{ .unloaded = {} },
                         .contents = .{ .not_available = {} },
                         .status = .never_loaded,
                         .root_container = .{
                             .file_scope = root_scope,
                             .decls = .{},
+                            .ty = Type.initPayload(&struct_payload.base),
                         },
                     };
                     break :rs &root_scope.base;
@@ -1022,6 +1027,17 @@ pub fn update(self: *Compilation) !void {
                     else => |e| return e,
                 };
             }
+
+            // TODO only analyze imports if they are still referenced
+            for (module.import_table.items()) |entry| {
+                entry.value.unload(module.gpa);
+                module.analyzeContainer(&entry.value.root_container) catch |err| switch (err) {
+                    error.AnalysisFail => {
+                        assert(self.totalErrorCount() != 0);
+                    },
+                    else => |e| return e,
+                };
+            }
         }
     }
 
src/main.zig
@@ -1446,6 +1446,11 @@ fn buildOutputType(
             cleanup_root_dir = dir;
             root_pkg_memory.root_src_directory = .{ .path = p, .handle = dir };
             root_pkg_memory.root_src_path = try fs.path.relative(arena, p, src_path);
+        } else if (fs.path.dirname(src_path)) |p| {
+            const dir = try fs.cwd().openDir(p, .{});
+            cleanup_root_dir = dir;
+            root_pkg_memory.root_src_directory = .{ .path = p, .handle = dir };
+            root_pkg_memory.root_src_path = fs.path.basename(src_path);
         } else {
             root_pkg_memory.root_src_directory = .{ .path = null, .handle = fs.cwd() };
             root_pkg_memory.root_src_path = src_path;
src/Module.zig
@@ -70,14 +70,14 @@ deletion_set: ArrayListUnmanaged(*Decl) = .{},
 /// Error tags and their values, tag names are duped with mod.gpa.
 global_error_set: std.StringHashMapUnmanaged(u16) = .{},
 
+/// Keys are fully qualified paths
+import_table: std.StringArrayHashMapUnmanaged(*Scope.File) = .{},
+
 /// Incrementing integer used to compare against the corresponding Decl
 /// field to determine whether a Decl's status applies to an ongoing update, or a
 /// previous analysis.
 generation: u32 = 0,
 
-/// Keys are fully qualified paths
-import_table: std.StringArrayHashMapUnmanaged(*Scope.File) = .{},
-
 stage1_flags: packed struct {
     have_winmain: bool = false,
     have_wwinmain: bool = false,
@@ -2392,10 +2392,7 @@ pub fn analyzeSlice(self: *Module, scope: *Scope, src: usize, array_ptr: *Inst,
 
 pub fn analyzeImport(self: *Module, scope: *Scope, src: usize, target_string: []const u8) !*Scope.File {
     // TODO if (package_table.get(target_string)) |pkg|
-
-    const file_path = try std.fs.path.join(scope.arena(), &[_][]const u8{ self.root_pkg.root_src_dir_path, target_string });
-
-    if (self.import_table.get(file_path)) |some| {
+    if (self.import_table.get(target_string)) |some| {
         return some;
     }
 
@@ -2404,10 +2401,15 @@ pub fn analyzeImport(self: *Module, scope: *Scope, src: usize, target_string: []
 
     // TODO Scope.Container arena for ty and sub_file_path
     const struct_payload = try self.gpa.create(Type.Payload.EmptyStruct);
+    errdefer self.gpa.destroy(struct_payload);
     const file_scope = try self.gpa.create(Scope.File);
+    errdefer self.gpa.destroy(file_scope);
+    const file_path = try self.gpa.dupe(u8, target_string);
+    errdefer self.gpa.free(file_path);
+
     struct_payload.* = .{ .scope = &file_scope.root_container };
     file_scope.* = .{
-        .sub_file_path = try self.gpa.dupe(u8, file_path),
+        .sub_file_path = file_path,
         .source = .{ .unloaded = {} },
         .contents = .{ .not_available = {} },
         .status = .never_loaded,
@@ -2419,7 +2421,7 @@ pub fn analyzeImport(self: *Module, scope: *Scope, src: usize, target_string: []
     };
     self.analyzeContainer(&file_scope.root_container) catch |err| switch (err) {
         error.AnalysisFail => {
-            assert(self.totalErrorCount() != 0);
+            assert(self.comp.totalErrorCount() != 0);
         },
         else => |e| return e,
     };