From 20ae15917c5cded10a01b85c2cba77041dacef1c Mon Sep 17 00:00:00 2001 From: Vexu Date: Fri, 4 Sep 2020 23:34:44 +0300 Subject: stage2: add import builtin stub --- src/Module.zig | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src/Module.zig') diff --git a/src/Module.zig b/src/Module.zig index 4fcf72f4ff..9d6510fe7f 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -2381,6 +2381,11 @@ pub fn analyzeSlice(self: *Module, scope: *Scope, src: usize, array_ptr: *Inst, return self.fail(scope, src, "TODO implement analysis of slice", .{}); } +pub fn analyzeImport(self: *Module, scope: *Scope, src: usize, target_string: []const u8) InnerError!*Inst { + // TODO actually try to import + return self.constType(scope, src, Type.initTag(.empty_struct)); +} + /// Asserts that lhs and rhs types are both numeric. pub fn cmpNumeric( self: *Module, -- cgit v1.2.3 From 7d910b024bd47d005030f9f3351e4923b2e0edc0 Mon Sep 17 00:00:00 2001 From: Vexu Date: Wed, 9 Sep 2020 17:41:51 +0300 Subject: stage2: very basic imports --- src/Module.zig | 49 ++++++++++++++++++++++++++++++++++++++++++------- src/type.zig | 13 +++++++++++-- src/value.zig | 1 + src/zir_sema.zig | 14 +++++++++++++- 4 files changed, 67 insertions(+), 10 deletions(-) (limited to 'src/Module.zig') diff --git a/src/Module.zig b/src/Module.zig index 9d6510fe7f..69097f4aba 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -75,6 +75,9 @@ global_error_set: std.StringHashMapUnmanaged(u16) = .{}, /// previous analysis. generation: u32 = 0, +/// Keys are fully qualified paths +import_table: std.StringHashMapUnmanaged(*Scope.File) = .{}, + stage1_flags: packed struct { have_winmain: bool = false, have_wwinmain: bool = false, @@ -208,7 +211,7 @@ pub const Decl = struct { .container => { const container = @fieldParentPtr(Scope.Container, "base", self.scope); const tree = container.file_scope.contents.tree; - // TODO Container should have it's own decls() + // TODO Container should have its own decls() const decl_node = tree.root_node.decls()[self.src_index]; return tree.token_locs[decl_node.firstToken()].start; }, @@ -532,12 +535,12 @@ pub const Scope = struct { /// Direct children of the file. decls: std.AutoArrayHashMapUnmanaged(*Decl, void), - - // TODO implement container types and put this in a status union - // ty: Type + ty: Type, pub fn deinit(self: *Container, gpa: *Allocator) void { self.decls.deinit(gpa); + // TODO either Container of File should have an arena for sub_file_path and ty + gpa.destroy(self.ty.cast(Type.Payload.EmptyStruct).?); self.* = undefined; } @@ -2381,9 +2384,41 @@ pub fn analyzeSlice(self: *Module, scope: *Scope, src: usize, array_ptr: *Inst, return self.fail(scope, src, "TODO implement analysis of slice", .{}); } -pub fn analyzeImport(self: *Module, scope: *Scope, src: usize, target_string: []const u8) InnerError!*Inst { - // TODO actually try to import - return self.constType(scope, src, Type.initTag(.empty_struct)); +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| { + return some; + } + + // TODO check for imports outside of pkg path + if (false) return error.ImportOutsidePkgPath; + + // TODO Scope.Container arena for ty and sub_file_path + const struct_payload = try self.gpa.create(Type.Payload.EmptyStruct); + const file_scope = try self.gpa.create(Scope.File); + struct_payload.* = .{ .scope = &file_scope.root_container }; + file_scope.* = .{ + .sub_file_path = try self.gpa.dupe(u8, file_path), + .source = .{ .unloaded = {} }, + .contents = .{ .not_available = {} }, + .status = .never_loaded, + .root_container = .{ + .file_scope = file_scope, + .decls = .{}, + .ty = Type.initPayload(&struct_payload.base), + }, + }; + self.analyzeContainer(&file_scope.root_container) catch |err| switch (err) { + error.AnalysisFail => { + assert(self.totalErrorCount() != 0); + }, + else => |e| return e, + }; + try self.import_table.put(self.gpa, file_scope.sub_file_path, file_scope); + return file_scope; } /// Asserts that lhs and rhs types are both numeric. diff --git a/src/type.zig b/src/type.zig index 8f9096fb94..bcce9d6edd 100644 --- a/src/type.zig +++ b/src/type.zig @@ -354,7 +354,6 @@ pub const Type = extern union { .enum_literal, .anyerror_void_error_union, .@"anyframe", - .empty_struct, => unreachable, .array_u8_sentinel_0 => return self.copyPayloadShallow(allocator, Payload.Array_u8_Sentinel0), @@ -442,6 +441,7 @@ pub const Type = extern union { }, .error_set => return self.copyPayloadShallow(allocator, Payload.ErrorSet), .error_set_single => return self.copyPayloadShallow(allocator, Payload.ErrorSetSingle), + .empty_struct => return self.copyPayloadShallow(allocator, Payload.EmptyStruct), } } @@ -508,6 +508,7 @@ pub const Type = extern union { .@"null" => return out_stream.writeAll("@Type(.Null)"), .@"undefined" => return out_stream.writeAll("@Type(.Undefined)"), + // TODO this should print the structs name .empty_struct => return out_stream.writeAll("struct {}"), .@"anyframe" => return out_stream.writeAll("anyframe"), .anyerror_void_error_union => return out_stream.writeAll("anyerror!void"), @@ -2837,7 +2838,6 @@ pub const Type = extern union { single_const_pointer_to_comptime_int, anyerror_void_error_union, @"anyframe", - empty_struct, const_slice_u8, // See last_no_payload_tag below. // After this, the tag requires a payload. @@ -2864,6 +2864,7 @@ pub const Type = extern union { anyframe_T, error_set, error_set_single, + empty_struct, pub const last_no_payload_tag = Tag.const_slice_u8; pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1; @@ -2971,6 +2972,14 @@ pub const Type = extern union { /// memory is owned by `Module` name: []const u8, }; + + /// Mostly used for namespace like structs with zero fields. + /// Most commonly used for files. + pub const EmptyStruct = struct { + base: Payload = .{ .tag = .empty_struct }, + + scope: *Module.Scope.Container, + }; }; }; diff --git a/src/value.zig b/src/value.zig index cdb99ce490..6e38b1bed4 100644 --- a/src/value.zig +++ b/src/value.zig @@ -314,6 +314,7 @@ pub const Value = extern union { .enum_literal_type => return out_stream.writeAll("@Type(.EnumLiteral)"), .anyframe_type => return out_stream.writeAll("anyframe"), + // TODO this should print `NAME{}` .empty_struct_value => return out_stream.writeAll("struct {}{}"), .null_value => return out_stream.writeAll("null"), .undef => return out_stream.writeAll("undefined"), diff --git a/src/zir_sema.zig b/src/zir_sema.zig index 63db1a4551..4ba8d1e431 100644 --- a/src/zir_sema.zig +++ b/src/zir_sema.zig @@ -1194,7 +1194,19 @@ fn analyzeInstSliceStart(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) Inn fn analyzeInstImport(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst { const operand = try resolveConstString(mod, scope, inst.positionals.operand); - return mod.analyzeImport(scope, inst.base.src, operand); + const file_scope = mod.analyzeImport(scope, inst.base.src, operand) catch |err| switch (err) { + // error.ImportOutsidePkgPath => { + // return mod.fail(scope, inst.base.src, "import of file outside package path: '{}'", .{operand}); + // }, + error.FileNotFound => { + return mod.fail(scope, inst.base.src, "unable to find '{}'", .{operand}); + }, + else => { + // TODO user friendly error to string + return mod.fail(scope, inst.base.src, "unable to open '{}': {}", .{operand, @errorName(err)}); + } + }; + return mod.constType(scope, inst.base.src, file_scope.root_container.ty); } fn analyzeInstShl(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerError!*Inst { -- cgit v1.2.3 From e246fe0f5bdf1168171f79570af16cd3e79665a6 Mon Sep 17 00:00:00 2001 From: Vexu Date: Wed, 9 Sep 2020 18:21:50 +0300 Subject: stage2: detect changes in imported files --- src/Module.zig | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'src/Module.zig') diff --git a/src/Module.zig b/src/Module.zig index 69097f4aba..46628de651 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -76,7 +76,7 @@ global_error_set: std.StringHashMapUnmanaged(u16) = .{}, generation: u32 = 0, /// Keys are fully qualified paths -import_table: std.StringHashMapUnmanaged(*Scope.File) = .{}, +import_table: std.StringArrayHashMapUnmanaged(*Scope.File) = .{}, stage1_flags: packed struct { have_winmain: bool = false, @@ -541,6 +541,7 @@ pub const Scope = struct { self.decls.deinit(gpa); // TODO either Container of File should have an arena for sub_file_path and ty gpa.destroy(self.ty.cast(Type.Payload.EmptyStruct).?); + gpa.free(self.file_scope.sub_file_path); self.* = undefined; } @@ -857,6 +858,11 @@ pub fn deinit(self: *Module) void { gpa.free(entry.key); } self.global_error_set.deinit(gpa); + + for (self.import_table.items()) |entry| { + entry.value.base.destroy(gpa); + } + self.import_table.deinit(gpa); } fn freeExportList(gpa: *Allocator, export_list: []*Export) void { -- cgit v1.2.3 From 6d3858dc8a5e5d510a6c9cc972357dda551628b3 Mon Sep 17 00:00:00 2001 From: Vexu Date: Wed, 30 Sep 2020 18:02:00 +0300 Subject: stage2: use directory handles for imports --- src/Compilation.zig | 18 +++++++++++++++++- src/Module.zig | 20 +++++++++++--------- src/main.zig | 5 +++++ 3 files changed, 33 insertions(+), 10 deletions(-) (limited to 'src/Module.zig') diff --git a/src/Compilation.zig b/src/Compilation.zig index 623635a6b0..71d91b8d2a 100644 --- a/src/Compilation.zig +++ b/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, + }; + } } } diff --git a/src/Module.zig b/src/Module.zig index 46628de651..75b6afffcd 100644 --- a/src/Module.zig +++ b/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, }; diff --git a/src/main.zig b/src/main.zig index d421322c17..5b83bac9ca 100644 --- a/src/main.zig +++ b/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; -- cgit v1.2.3