| author | |
| committer | |
| log | 302a69f127ae8542f49d9cd07c7cc49f3bbd6181 |
| tree | 063f062e7701e4679a0e97ad1a25021294663640 |
| parent | 0e2d858d69ee1595bb58d936f83f0e0248d54d68 |
| parent | 6d3858dc8a5e5d510a6c9cc972357dda551628b3 |
| signature |
Stage2: basic imports10 files changed, 301 insertions(+), 5 deletions(-)
src/Compilation.zig+17-1| ... | @@ -8,6 +8,7 @@ const log = std.log.scoped(.compilation); | ... | @@ -8,6 +8,7 @@ const log = std.log.scoped(.compilation); |
| 8 | const Target = std.Target; | 8 | const Target = std.Target; |
| 9 | 9 | ||
| 10 | const Value = @import("value.zig").Value; | 10 | const Value = @import("value.zig").Value; |
| 11 | const Type = @import("type.zig").Type; | ||
| 11 | const target_util = @import("target.zig"); | 12 | const target_util = @import("target.zig"); |
| 12 | const Package = @import("Package.zig"); | 13 | const Package = @import("Package.zig"); |
| 13 | const link = @import("link.zig"); | 14 | const link = @import("link.zig"); |
| ... | @@ -640,15 +641,19 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { | ... | @@ -640,15 +641,19 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { |
| 640 | 641 | ||
| 641 | const root_scope = rs: { | 642 | const root_scope = rs: { |
| 642 | if (mem.endsWith(u8, root_pkg.root_src_path, ".zig")) { | 643 | if (mem.endsWith(u8, root_pkg.root_src_path, ".zig")) { |
| 644 | const struct_payload = try gpa.create(Type.Payload.EmptyStruct); | ||
| 643 | const root_scope = try gpa.create(Module.Scope.File); | 645 | const root_scope = try gpa.create(Module.Scope.File); |
| 646 | struct_payload.* = .{ .scope = &root_scope.root_container }; | ||
| 644 | root_scope.* = .{ | 647 | root_scope.* = .{ |
| 645 | .sub_file_path = root_pkg.root_src_path, | 648 | // TODO this is duped so it can be freed in Container.deinit |
| 649 | .sub_file_path = try gpa.dupe(u8, root_pkg.root_src_path), | ||
| 646 | .source = .{ .unloaded = {} }, | 650 | .source = .{ .unloaded = {} }, |
| 647 | .contents = .{ .not_available = {} }, | 651 | .contents = .{ .not_available = {} }, |
| 648 | .status = .never_loaded, | 652 | .status = .never_loaded, |
| 649 | .root_container = .{ | 653 | .root_container = .{ |
| 650 | .file_scope = root_scope, | 654 | .file_scope = root_scope, |
| 651 | .decls = .{}, | 655 | .decls = .{}, |
| 656 | .ty = Type.initPayload(&struct_payload.base), | ||
| 652 | }, | 657 | }, |
| 653 | }; | 658 | }; |
| 654 | break :rs &root_scope.base; | 659 | break :rs &root_scope.base; |
| ... | @@ -1025,6 +1030,17 @@ pub fn update(self: *Compilation) !void { | ... | @@ -1025,6 +1030,17 @@ pub fn update(self: *Compilation) !void { |
| 1025 | else => |e| return e, | 1030 | else => |e| return e, |
| 1026 | }; | 1031 | }; |
| 1027 | } | 1032 | } |
| 1033 | |||
| 1034 | // TODO only analyze imports if they are still referenced | ||
| 1035 | for (module.import_table.items()) |entry| { | ||
| 1036 | entry.value.unload(module.gpa); | ||
| 1037 | module.analyzeContainer(&entry.value.root_container) catch |err| switch (err) { | ||
| 1038 | error.AnalysisFail => { | ||
| 1039 | assert(self.totalErrorCount() != 0); | ||
| 1040 | }, | ||
| 1041 | else => |e| return e, | ||
| 1042 | }; | ||
| 1043 | } | ||
| 1028 | } | 1044 | } |
| 1029 | } | 1045 | } |
| 1030 | 1046 |
src/Module.zig+52-4| ... | @@ -70,6 +70,9 @@ deletion_set: ArrayListUnmanaged(*Decl) = .{}, | ... | @@ -70,6 +70,9 @@ deletion_set: ArrayListUnmanaged(*Decl) = .{}, |
| 70 | /// Error tags and their values, tag names are duped with mod.gpa. | 70 | /// Error tags and their values, tag names are duped with mod.gpa. |
| 71 | global_error_set: std.StringHashMapUnmanaged(u16) = .{}, | 71 | global_error_set: std.StringHashMapUnmanaged(u16) = .{}, |
| 72 | 72 | ||
| 73 | /// Keys are fully qualified paths | ||
| 74 | import_table: std.StringArrayHashMapUnmanaged(*Scope.File) = .{}, | ||
| 75 | |||
| 73 | /// Incrementing integer used to compare against the corresponding Decl | 76 | /// Incrementing integer used to compare against the corresponding Decl |
| 74 | /// field to determine whether a Decl's status applies to an ongoing update, or a | 77 | /// field to determine whether a Decl's status applies to an ongoing update, or a |
| 75 | /// previous analysis. | 78 | /// previous analysis. |
| ... | @@ -208,7 +211,7 @@ pub const Decl = struct { | ... | @@ -208,7 +211,7 @@ pub const Decl = struct { |
| 208 | .container => { | 211 | .container => { |
| 209 | const container = @fieldParentPtr(Scope.Container, "base", self.scope); | 212 | const container = @fieldParentPtr(Scope.Container, "base", self.scope); |
| 210 | const tree = container.file_scope.contents.tree; | 213 | const tree = container.file_scope.contents.tree; |
| 211 | // TODO Container should have it's own decls() | 214 | // TODO Container should have its own decls() |
| 212 | const decl_node = tree.root_node.decls()[self.src_index]; | 215 | const decl_node = tree.root_node.decls()[self.src_index]; |
| 213 | return tree.token_locs[decl_node.firstToken()].start; | 216 | return tree.token_locs[decl_node.firstToken()].start; |
| 214 | }, | 217 | }, |
| ... | @@ -532,12 +535,13 @@ pub const Scope = struct { | ... | @@ -532,12 +535,13 @@ pub const Scope = struct { |
| 532 | 535 | ||
| 533 | /// Direct children of the file. | 536 | /// Direct children of the file. |
| 534 | decls: std.AutoArrayHashMapUnmanaged(*Decl, void), | 537 | decls: std.AutoArrayHashMapUnmanaged(*Decl, void), |
| 535 | 538 | ty: Type, | |
| 536 | // TODO implement container types and put this in a status union | ||
| 537 | // ty: Type | ||
| 538 | 539 | ||
| 539 | pub fn deinit(self: *Container, gpa: *Allocator) void { | 540 | pub fn deinit(self: *Container, gpa: *Allocator) void { |
| 540 | self.decls.deinit(gpa); | 541 | self.decls.deinit(gpa); |
| 542 | // TODO either Container of File should have an arena for sub_file_path and ty | ||
| 543 | gpa.destroy(self.ty.cast(Type.Payload.EmptyStruct).?); | ||
| 544 | gpa.free(self.file_scope.sub_file_path); | ||
| 541 | self.* = undefined; | 545 | self.* = undefined; |
| 542 | } | 546 | } |
| 543 | 547 | ||
| ... | @@ -854,6 +858,11 @@ pub fn deinit(self: *Module) void { | ... | @@ -854,6 +858,11 @@ pub fn deinit(self: *Module) void { |
| 854 | gpa.free(entry.key); | 858 | gpa.free(entry.key); |
| 855 | } | 859 | } |
| 856 | self.global_error_set.deinit(gpa); | 860 | self.global_error_set.deinit(gpa); |
| 861 | |||
| 862 | for (self.import_table.items()) |entry| { | ||
| 863 | entry.value.base.destroy(gpa); | ||
| 864 | } | ||
| 865 | self.import_table.deinit(gpa); | ||
| 857 | } | 866 | } |
| 858 | 867 | ||
| 859 | fn freeExportList(gpa: *Allocator, export_list: []*Export) void { | 868 | fn freeExportList(gpa: *Allocator, export_list: []*Export) void { |
| ... | @@ -2381,6 +2390,45 @@ pub fn analyzeSlice(self: *Module, scope: *Scope, src: usize, array_ptr: *Inst, | ... | @@ -2381,6 +2390,45 @@ pub fn analyzeSlice(self: *Module, scope: *Scope, src: usize, array_ptr: *Inst, |
| 2381 | return self.fail(scope, src, "TODO implement analysis of slice", .{}); | 2390 | return self.fail(scope, src, "TODO implement analysis of slice", .{}); |
| 2382 | } | 2391 | } |
| 2383 | 2392 | ||
| 2393 | pub fn analyzeImport(self: *Module, scope: *Scope, src: usize, target_string: []const u8) !*Scope.File { | ||
| 2394 | // TODO if (package_table.get(target_string)) |pkg| | ||
| 2395 | if (self.import_table.get(target_string)) |some| { | ||
| 2396 | return some; | ||
| 2397 | } | ||
| 2398 | |||
| 2399 | // TODO check for imports outside of pkg path | ||
| 2400 | if (false) return error.ImportOutsidePkgPath; | ||
| 2401 | |||
| 2402 | // TODO Scope.Container arena for ty and sub_file_path | ||
| 2403 | const struct_payload = try self.gpa.create(Type.Payload.EmptyStruct); | ||
| 2404 | errdefer self.gpa.destroy(struct_payload); | ||
| 2405 | const file_scope = try self.gpa.create(Scope.File); | ||
| 2406 | errdefer self.gpa.destroy(file_scope); | ||
| 2407 | const file_path = try self.gpa.dupe(u8, target_string); | ||
| 2408 | errdefer self.gpa.free(file_path); | ||
| 2409 | |||
| 2410 | struct_payload.* = .{ .scope = &file_scope.root_container }; | ||
| 2411 | file_scope.* = .{ | ||
| 2412 | .sub_file_path = file_path, | ||
| 2413 | .source = .{ .unloaded = {} }, | ||
| 2414 | .contents = .{ .not_available = {} }, | ||
| 2415 | .status = .never_loaded, | ||
| 2416 | .root_container = .{ | ||
| 2417 | .file_scope = file_scope, | ||
| 2418 | .decls = .{}, | ||
| 2419 | .ty = Type.initPayload(&struct_payload.base), | ||
| 2420 | }, | ||
| 2421 | }; | ||
| 2422 | self.analyzeContainer(&file_scope.root_container) catch |err| switch (err) { | ||
| 2423 | error.AnalysisFail => { | ||
| 2424 | assert(self.comp.totalErrorCount() != 0); | ||
| 2425 | }, | ||
| 2426 | else => |e| return e, | ||
| 2427 | }; | ||
| 2428 | try self.import_table.put(self.gpa, file_scope.sub_file_path, file_scope); | ||
| 2429 | return file_scope; | ||
| 2430 | } | ||
| 2431 | |||
| 2384 | /// Asserts that lhs and rhs types are both numeric. | 2432 | /// Asserts that lhs and rhs types are both numeric. |
| 2385 | pub fn cmpNumeric( | 2433 | pub fn cmpNumeric( |
| 2386 | self: *Module, | 2434 | self: *Module, |
src/astgen.zig+11| ... | @@ -1973,6 +1973,15 @@ fn bitCast(mod: *Module, scope: *Scope, rl: ResultLoc, call: *ast.Node.BuiltinCa | ... | @@ -1973,6 +1973,15 @@ fn bitCast(mod: *Module, scope: *Scope, rl: ResultLoc, call: *ast.Node.BuiltinCa |
| 1973 | } | 1973 | } |
| 1974 | } | 1974 | } |
| 1975 | 1975 | ||
| 1976 | fn import(mod: *Module, scope: *Scope, call: *ast.Node.BuiltinCall) InnerError!*zir.Inst { | ||
| 1977 | try ensureBuiltinParamCount(mod, scope, call, 1); | ||
| 1978 | const tree = scope.tree(); | ||
| 1979 | const src = tree.token_locs[call.builtin_token].start; | ||
| 1980 | const params = call.params(); | ||
| 1981 | const target = try expr(mod, scope, .none, params[0]); | ||
| 1982 | return addZIRUnOp(mod, scope, src, .import, target); | ||
| 1983 | } | ||
| 1984 | |||
| 1976 | fn builtinCall(mod: *Module, scope: *Scope, rl: ResultLoc, call: *ast.Node.BuiltinCall) InnerError!*zir.Inst { | 1985 | fn builtinCall(mod: *Module, scope: *Scope, rl: ResultLoc, call: *ast.Node.BuiltinCall) InnerError!*zir.Inst { |
| 1977 | const tree = scope.tree(); | 1986 | const tree = scope.tree(); |
| 1978 | const builtin_name = tree.tokenSlice(call.builtin_token); | 1987 | const builtin_name = tree.tokenSlice(call.builtin_token); |
| ... | @@ -1995,6 +2004,8 @@ fn builtinCall(mod: *Module, scope: *Scope, rl: ResultLoc, call: *ast.Node.Built | ... | @@ -1995,6 +2004,8 @@ fn builtinCall(mod: *Module, scope: *Scope, rl: ResultLoc, call: *ast.Node.Built |
| 1995 | } else if (mem.eql(u8, builtin_name, "@breakpoint")) { | 2004 | } else if (mem.eql(u8, builtin_name, "@breakpoint")) { |
| 1996 | const src = tree.token_locs[call.builtin_token].start; | 2005 | const src = tree.token_locs[call.builtin_token].start; |
| 1997 | return rlWrap(mod, scope, rl, try addZIRNoOp(mod, scope, src, .breakpoint)); | 2006 | return rlWrap(mod, scope, rl, try addZIRNoOp(mod, scope, src, .breakpoint)); |
| 2007 | } else if (mem.eql(u8, builtin_name, "@import")) { | ||
| 2008 | return rlWrap(mod, scope, rl, try import(mod, scope, call)); | ||
| 1998 | } else { | 2009 | } else { |
| 1999 | return mod.failTok(scope, call.builtin_token, "invalid builtin function: '{}'", .{builtin_name}); | 2010 | return mod.failTok(scope, call.builtin_token, "invalid builtin function: '{}'", .{builtin_name}); |
| 2000 | } | 2011 | } |
src/main.zig+5| ... | @@ -1454,6 +1454,11 @@ fn buildOutputType( | ... | @@ -1454,6 +1454,11 @@ fn buildOutputType( |
| 1454 | cleanup_root_dir = dir; | 1454 | cleanup_root_dir = dir; |
| 1455 | root_pkg_memory.root_src_directory = .{ .path = p, .handle = dir }; | 1455 | root_pkg_memory.root_src_directory = .{ .path = p, .handle = dir }; |
| 1456 | root_pkg_memory.root_src_path = try fs.path.relative(arena, p, src_path); | 1456 | root_pkg_memory.root_src_path = try fs.path.relative(arena, p, src_path); |
| 1457 | } else if (fs.path.dirname(src_path)) |p| { | ||
| 1458 | const dir = try fs.cwd().openDir(p, .{}); | ||
| 1459 | cleanup_root_dir = dir; | ||
| 1460 | root_pkg_memory.root_src_directory = .{ .path = p, .handle = dir }; | ||
| 1461 | root_pkg_memory.root_src_path = fs.path.basename(src_path); | ||
| 1457 | } else { | 1462 | } else { |
| 1458 | root_pkg_memory.root_src_directory = .{ .path = null, .handle = fs.cwd() }; | 1463 | root_pkg_memory.root_src_directory = .{ .path = null, .handle = fs.cwd() }; |
| 1459 | root_pkg_memory.root_src_path = src_path; | 1464 | root_pkg_memory.root_src_path = src_path; |
src/test.zig+15| ... | @@ -56,6 +56,12 @@ pub const TestContext = struct { | ... | @@ -56,6 +56,12 @@ pub const TestContext = struct { |
| 56 | }, | 56 | }, |
| 57 | }; | 57 | }; |
| 58 | 58 | ||
| 59 | pub const File = struct { | ||
| 60 | /// Contents of the importable file. Doesn't yet support incremental updates. | ||
| 61 | src: [:0]const u8, | ||
| 62 | path: []const u8, | ||
| 63 | }; | ||
| 64 | |||
| 59 | pub const TestType = enum { | 65 | pub const TestType = enum { |
| 60 | Zig, | 66 | Zig, |
| 61 | ZIR, | 67 | ZIR, |
| ... | @@ -78,6 +84,8 @@ pub const TestContext = struct { | ... | @@ -78,6 +84,8 @@ pub const TestContext = struct { |
| 78 | extension: TestType, | 84 | extension: TestType, |
| 79 | cbe: bool = false, | 85 | cbe: bool = false, |
| 80 | 86 | ||
| 87 | files: std.ArrayList(File), | ||
| 88 | |||
| 81 | /// Adds a subcase in which the module is updated with `src`, and the | 89 | /// Adds a subcase in which the module is updated with `src`, and the |
| 82 | /// resulting ZIR is validated against `result`. | 90 | /// resulting ZIR is validated against `result`. |
| 83 | pub fn addTransform(self: *Case, src: [:0]const u8, result: [:0]const u8) void { | 91 | pub fn addTransform(self: *Case, src: [:0]const u8, result: [:0]const u8) void { |
| ... | @@ -156,6 +164,7 @@ pub const TestContext = struct { | ... | @@ -156,6 +164,7 @@ pub const TestContext = struct { |
| 156 | .updates = std.ArrayList(Update).init(ctx.cases.allocator), | 164 | .updates = std.ArrayList(Update).init(ctx.cases.allocator), |
| 157 | .output_mode = .Exe, | 165 | .output_mode = .Exe, |
| 158 | .extension = T, | 166 | .extension = T, |
| 167 | .files = std.ArrayList(File).init(ctx.cases.allocator), | ||
| 159 | }) catch unreachable; | 168 | }) catch unreachable; |
| 160 | return &ctx.cases.items[ctx.cases.items.len - 1]; | 169 | return &ctx.cases.items[ctx.cases.items.len - 1]; |
| 161 | } | 170 | } |
| ... | @@ -182,6 +191,7 @@ pub const TestContext = struct { | ... | @@ -182,6 +191,7 @@ pub const TestContext = struct { |
| 182 | .updates = std.ArrayList(Update).init(ctx.cases.allocator), | 191 | .updates = std.ArrayList(Update).init(ctx.cases.allocator), |
| 183 | .output_mode = .Obj, | 192 | .output_mode = .Obj, |
| 184 | .extension = T, | 193 | .extension = T, |
| 194 | .files = std.ArrayList(File).init(ctx.cases.allocator), | ||
| 185 | }) catch unreachable; | 195 | }) catch unreachable; |
| 186 | return &ctx.cases.items[ctx.cases.items.len - 1]; | 196 | return &ctx.cases.items[ctx.cases.items.len - 1]; |
| 187 | } | 197 | } |
| ... | @@ -204,6 +214,7 @@ pub const TestContext = struct { | ... | @@ -204,6 +214,7 @@ pub const TestContext = struct { |
| 204 | .output_mode = .Obj, | 214 | .output_mode = .Obj, |
| 205 | .extension = T, | 215 | .extension = T, |
| 206 | .cbe = true, | 216 | .cbe = true, |
| 217 | .files = std.ArrayList(File).init(ctx.cases.allocator), | ||
| 207 | }) catch unreachable; | 218 | }) catch unreachable; |
| 208 | return &ctx.cases.items[ctx.cases.items.len - 1]; | 219 | return &ctx.cases.items[ctx.cases.items.len - 1]; |
| 209 | } | 220 | } |
| ... | @@ -505,6 +516,10 @@ pub const TestContext = struct { | ... | @@ -505,6 +516,10 @@ pub const TestContext = struct { |
| 505 | }); | 516 | }); |
| 506 | defer comp.destroy(); | 517 | defer comp.destroy(); |
| 507 | 518 | ||
| 519 | for (case.files.items) |file| { | ||
| 520 | try tmp.dir.writeFile(file.path, file.src); | ||
| 521 | } | ||
| 522 | |||
| 508 | for (case.updates.items) |update, update_index| { | 523 | for (case.updates.items) |update, update_index| { |
| 509 | var update_node = root_node.start("update", 3); | 524 | var update_node = root_node.start("update", 3); |
| 510 | update_node.activate(); | 525 | update_node.activate(); |
src/type.zig+112| ... | @@ -89,6 +89,8 @@ pub const Type = extern union { | ... | @@ -89,6 +89,8 @@ pub const Type = extern union { |
| 89 | .anyerror_void_error_union, .error_union => return .ErrorUnion, | 89 | .anyerror_void_error_union, .error_union => return .ErrorUnion, |
| 90 | 90 | ||
| 91 | .anyframe_T, .@"anyframe" => return .AnyFrame, | 91 | .anyframe_T, .@"anyframe" => return .AnyFrame, |
| 92 | |||
| 93 | .empty_struct => return .Struct, | ||
| 92 | } | 94 | } |
| 93 | } | 95 | } |
| 94 | 96 | ||
| ... | @@ -439,6 +441,7 @@ pub const Type = extern union { | ... | @@ -439,6 +441,7 @@ pub const Type = extern union { |
| 439 | }, | 441 | }, |
| 440 | .error_set => return self.copyPayloadShallow(allocator, Payload.ErrorSet), | 442 | .error_set => return self.copyPayloadShallow(allocator, Payload.ErrorSet), |
| 441 | .error_set_single => return self.copyPayloadShallow(allocator, Payload.ErrorSetSingle), | 443 | .error_set_single => return self.copyPayloadShallow(allocator, Payload.ErrorSetSingle), |
| 444 | .empty_struct => return self.copyPayloadShallow(allocator, Payload.EmptyStruct), | ||
| 442 | } | 445 | } |
| 443 | } | 446 | } |
| 444 | 447 | ||
| ... | @@ -505,6 +508,8 @@ pub const Type = extern union { | ... | @@ -505,6 +508,8 @@ pub const Type = extern union { |
| 505 | .@"null" => return out_stream.writeAll("@Type(.Null)"), | 508 | .@"null" => return out_stream.writeAll("@Type(.Null)"), |
| 506 | .@"undefined" => return out_stream.writeAll("@Type(.Undefined)"), | 509 | .@"undefined" => return out_stream.writeAll("@Type(.Undefined)"), |
| 507 | 510 | ||
| 511 | // TODO this should print the structs name | ||
| 512 | .empty_struct => return out_stream.writeAll("struct {}"), | ||
| 508 | .@"anyframe" => return out_stream.writeAll("anyframe"), | 513 | .@"anyframe" => return out_stream.writeAll("anyframe"), |
| 509 | .anyerror_void_error_union => return out_stream.writeAll("anyerror!void"), | 514 | .anyerror_void_error_union => return out_stream.writeAll("anyerror!void"), |
| 510 | .const_slice_u8 => return out_stream.writeAll("[]const u8"), | 515 | .const_slice_u8 => return out_stream.writeAll("[]const u8"), |
| ... | @@ -788,6 +793,7 @@ pub const Type = extern union { | ... | @@ -788,6 +793,7 @@ pub const Type = extern union { |
| 788 | .@"null", | 793 | .@"null", |
| 789 | .@"undefined", | 794 | .@"undefined", |
| 790 | .enum_literal, | 795 | .enum_literal, |
| 796 | .empty_struct, | ||
| 791 | => false, | 797 | => false, |
| 792 | }; | 798 | }; |
| 793 | } | 799 | } |
| ... | @@ -910,6 +916,7 @@ pub const Type = extern union { | ... | @@ -910,6 +916,7 @@ pub const Type = extern union { |
| 910 | .@"null", | 916 | .@"null", |
| 911 | .@"undefined", | 917 | .@"undefined", |
| 912 | .enum_literal, | 918 | .enum_literal, |
| 919 | .empty_struct, | ||
| 913 | => unreachable, | 920 | => unreachable, |
| 914 | }; | 921 | }; |
| 915 | } | 922 | } |
| ... | @@ -932,6 +939,7 @@ pub const Type = extern union { | ... | @@ -932,6 +939,7 @@ pub const Type = extern union { |
| 932 | .@"undefined" => unreachable, | 939 | .@"undefined" => unreachable, |
| 933 | .enum_literal => unreachable, | 940 | .enum_literal => unreachable, |
| 934 | .single_const_pointer_to_comptime_int => unreachable, | 941 | .single_const_pointer_to_comptime_int => unreachable, |
| 942 | .empty_struct => unreachable, | ||
| 935 | 943 | ||
| 936 | .u8, | 944 | .u8, |
| 937 | .i8, | 945 | .i8, |
| ... | @@ -1107,6 +1115,7 @@ pub const Type = extern union { | ... | @@ -1107,6 +1115,7 @@ pub const Type = extern union { |
| 1107 | .anyerror_void_error_union, | 1115 | .anyerror_void_error_union, |
| 1108 | .error_set, | 1116 | .error_set, |
| 1109 | .error_set_single, | 1117 | .error_set_single, |
| 1118 | .empty_struct, | ||
| 1110 | => false, | 1119 | => false, |
| 1111 | 1120 | ||
| 1112 | .single_const_pointer, | 1121 | .single_const_pointer, |
| ... | @@ -1181,6 +1190,7 @@ pub const Type = extern union { | ... | @@ -1181,6 +1190,7 @@ pub const Type = extern union { |
| 1181 | .anyerror_void_error_union, | 1190 | .anyerror_void_error_union, |
| 1182 | .error_set, | 1191 | .error_set, |
| 1183 | .error_set_single, | 1192 | .error_set_single, |
| 1193 | .empty_struct, | ||
| 1184 | => false, | 1194 | => false, |
| 1185 | 1195 | ||
| 1186 | .const_slice, | 1196 | .const_slice, |
| ... | @@ -1252,6 +1262,7 @@ pub const Type = extern union { | ... | @@ -1252,6 +1262,7 @@ pub const Type = extern union { |
| 1252 | .anyerror_void_error_union, | 1262 | .anyerror_void_error_union, |
| 1253 | .error_set, | 1263 | .error_set, |
| 1254 | .error_set_single, | 1264 | .error_set_single, |
| 1265 | .empty_struct, | ||
| 1255 | => false, | 1266 | => false, |
| 1256 | 1267 | ||
| 1257 | .single_const_pointer, | 1268 | .single_const_pointer, |
| ... | @@ -1332,6 +1343,7 @@ pub const Type = extern union { | ... | @@ -1332,6 +1343,7 @@ pub const Type = extern union { |
| 1332 | .anyerror_void_error_union, | 1343 | .anyerror_void_error_union, |
| 1333 | .error_set, | 1344 | .error_set, |
| 1334 | .error_set_single, | 1345 | .error_set_single, |
| 1346 | .empty_struct, | ||
| 1335 | => false, | 1347 | => false, |
| 1336 | 1348 | ||
| 1337 | .pointer => { | 1349 | .pointer => { |
| ... | @@ -1407,6 +1419,7 @@ pub const Type = extern union { | ... | @@ -1407,6 +1419,7 @@ pub const Type = extern union { |
| 1407 | .anyerror_void_error_union, | 1419 | .anyerror_void_error_union, |
| 1408 | .error_set, | 1420 | .error_set, |
| 1409 | .error_set_single, | 1421 | .error_set_single, |
| 1422 | .empty_struct, | ||
| 1410 | => false, | 1423 | => false, |
| 1411 | 1424 | ||
| 1412 | .pointer => { | 1425 | .pointer => { |
| ... | @@ -1524,6 +1537,7 @@ pub const Type = extern union { | ... | @@ -1524,6 +1537,7 @@ pub const Type = extern union { |
| 1524 | .anyerror_void_error_union, | 1537 | .anyerror_void_error_union, |
| 1525 | .error_set, | 1538 | .error_set, |
| 1526 | .error_set_single, | 1539 | .error_set_single, |
| 1540 | .empty_struct, | ||
| 1527 | => unreachable, | 1541 | => unreachable, |
| 1528 | 1542 | ||
| 1529 | .array => self.cast(Payload.Array).?.elem_type, | 1543 | .array => self.cast(Payload.Array).?.elem_type, |
| ... | @@ -1651,6 +1665,7 @@ pub const Type = extern union { | ... | @@ -1651,6 +1665,7 @@ pub const Type = extern union { |
| 1651 | .anyerror_void_error_union, | 1665 | .anyerror_void_error_union, |
| 1652 | .error_set, | 1666 | .error_set, |
| 1653 | .error_set_single, | 1667 | .error_set_single, |
| 1668 | .empty_struct, | ||
| 1654 | => unreachable, | 1669 | => unreachable, |
| 1655 | 1670 | ||
| 1656 | .array => self.cast(Payload.Array).?.len, | 1671 | .array => self.cast(Payload.Array).?.len, |
| ... | @@ -1716,6 +1731,7 @@ pub const Type = extern union { | ... | @@ -1716,6 +1731,7 @@ pub const Type = extern union { |
| 1716 | .anyerror_void_error_union, | 1731 | .anyerror_void_error_union, |
| 1717 | .error_set, | 1732 | .error_set, |
| 1718 | .error_set_single, | 1733 | .error_set_single, |
| 1734 | .empty_struct, | ||
| 1719 | => unreachable, | 1735 | => unreachable, |
| 1720 | 1736 | ||
| 1721 | .single_const_pointer, | 1737 | .single_const_pointer, |
| ... | @@ -1798,6 +1814,7 @@ pub const Type = extern union { | ... | @@ -1798,6 +1814,7 @@ pub const Type = extern union { |
| 1798 | .anyerror_void_error_union, | 1814 | .anyerror_void_error_union, |
| 1799 | .error_set, | 1815 | .error_set, |
| 1800 | .error_set_single, | 1816 | .error_set_single, |
| 1817 | .empty_struct, | ||
| 1801 | => false, | 1818 | => false, |
| 1802 | 1819 | ||
| 1803 | .int_signed, | 1820 | .int_signed, |
| ... | @@ -1872,6 +1889,7 @@ pub const Type = extern union { | ... | @@ -1872,6 +1889,7 @@ pub const Type = extern union { |
| 1872 | .anyerror_void_error_union, | 1889 | .anyerror_void_error_union, |
| 1873 | .error_set, | 1890 | .error_set, |
| 1874 | .error_set_single, | 1891 | .error_set_single, |
| 1892 | .empty_struct, | ||
| 1875 | => false, | 1893 | => false, |
| 1876 | 1894 | ||
| 1877 | .int_unsigned, | 1895 | .int_unsigned, |
| ... | @@ -1936,6 +1954,7 @@ pub const Type = extern union { | ... | @@ -1936,6 +1954,7 @@ pub const Type = extern union { |
| 1936 | .anyerror_void_error_union, | 1954 | .anyerror_void_error_union, |
| 1937 | .error_set, | 1955 | .error_set, |
| 1938 | .error_set_single, | 1956 | .error_set_single, |
| 1957 | .empty_struct, | ||
| 1939 | => unreachable, | 1958 | => unreachable, |
| 1940 | 1959 | ||
| 1941 | .int_unsigned => .{ .signed = false, .bits = self.cast(Payload.IntUnsigned).?.bits }, | 1960 | .int_unsigned => .{ .signed = false, .bits = self.cast(Payload.IntUnsigned).?.bits }, |
| ... | @@ -2018,6 +2037,7 @@ pub const Type = extern union { | ... | @@ -2018,6 +2037,7 @@ pub const Type = extern union { |
| 2018 | .anyerror_void_error_union, | 2037 | .anyerror_void_error_union, |
| 2019 | .error_set, | 2038 | .error_set, |
| 2020 | .error_set_single, | 2039 | .error_set_single, |
| 2040 | .empty_struct, | ||
| 2021 | => false, | 2041 | => false, |
| 2022 | 2042 | ||
| 2023 | .usize, | 2043 | .usize, |
| ... | @@ -2129,6 +2149,7 @@ pub const Type = extern union { | ... | @@ -2129,6 +2149,7 @@ pub const Type = extern union { |
| 2129 | .anyerror_void_error_union, | 2149 | .anyerror_void_error_union, |
| 2130 | .error_set, | 2150 | .error_set, |
| 2131 | .error_set_single, | 2151 | .error_set_single, |
| 2152 | .empty_struct, | ||
| 2132 | => unreachable, | 2153 | => unreachable, |
| 2133 | }; | 2154 | }; |
| 2134 | } | 2155 | } |
| ... | @@ -2206,6 +2227,7 @@ pub const Type = extern union { | ... | @@ -2206,6 +2227,7 @@ pub const Type = extern union { |
| 2206 | .anyerror_void_error_union, | 2227 | .anyerror_void_error_union, |
| 2207 | .error_set, | 2228 | .error_set, |
| 2208 | .error_set_single, | 2229 | .error_set_single, |
| 2230 | .empty_struct, | ||
| 2209 | => unreachable, | 2231 | => unreachable, |
| 2210 | } | 2232 | } |
| 2211 | } | 2233 | } |
| ... | @@ -2282,6 +2304,7 @@ pub const Type = extern union { | ... | @@ -2282,6 +2304,7 @@ pub const Type = extern union { |
| 2282 | .anyerror_void_error_union, | 2304 | .anyerror_void_error_union, |
| 2283 | .error_set, | 2305 | .error_set, |
| 2284 | .error_set_single, | 2306 | .error_set_single, |
| 2307 | .empty_struct, | ||
| 2285 | => unreachable, | 2308 | => unreachable, |
| 2286 | } | 2309 | } |
| 2287 | } | 2310 | } |
| ... | @@ -2358,6 +2381,7 @@ pub const Type = extern union { | ... | @@ -2358,6 +2381,7 @@ pub const Type = extern union { |
| 2358 | .anyerror_void_error_union, | 2381 | .anyerror_void_error_union, |
| 2359 | .error_set, | 2382 | .error_set, |
| 2360 | .error_set_single, | 2383 | .error_set_single, |
| 2384 | .empty_struct, | ||
| 2361 | => unreachable, | 2385 | => unreachable, |
| 2362 | }; | 2386 | }; |
| 2363 | } | 2387 | } |
| ... | @@ -2431,6 +2455,7 @@ pub const Type = extern union { | ... | @@ -2431,6 +2455,7 @@ pub const Type = extern union { |
| 2431 | .anyerror_void_error_union, | 2455 | .anyerror_void_error_union, |
| 2432 | .error_set, | 2456 | .error_set, |
| 2433 | .error_set_single, | 2457 | .error_set_single, |
| 2458 | .empty_struct, | ||
| 2434 | => unreachable, | 2459 | => unreachable, |
| 2435 | }; | 2460 | }; |
| 2436 | } | 2461 | } |
| ... | @@ -2504,6 +2529,7 @@ pub const Type = extern union { | ... | @@ -2504,6 +2529,7 @@ pub const Type = extern union { |
| 2504 | .anyerror_void_error_union, | 2529 | .anyerror_void_error_union, |
| 2505 | .error_set, | 2530 | .error_set, |
| 2506 | .error_set_single, | 2531 | .error_set_single, |
| 2532 | .empty_struct, | ||
| 2507 | => unreachable, | 2533 | => unreachable, |
| 2508 | }; | 2534 | }; |
| 2509 | } | 2535 | } |
| ... | @@ -2577,6 +2603,7 @@ pub const Type = extern union { | ... | @@ -2577,6 +2603,7 @@ pub const Type = extern union { |
| 2577 | .anyerror_void_error_union, | 2603 | .anyerror_void_error_union, |
| 2578 | .error_set, | 2604 | .error_set, |
| 2579 | .error_set_single, | 2605 | .error_set_single, |
| 2606 | .empty_struct, | ||
| 2580 | => false, | 2607 | => false, |
| 2581 | }; | 2608 | }; |
| 2582 | } | 2609 | } |
| ... | @@ -2636,6 +2663,7 @@ pub const Type = extern union { | ... | @@ -2636,6 +2663,7 @@ pub const Type = extern union { |
| 2636 | .error_set_single, | 2663 | .error_set_single, |
| 2637 | => return null, | 2664 | => return null, |
| 2638 | 2665 | ||
| 2666 | .empty_struct => return Value.initTag(.empty_struct_value), | ||
| 2639 | .void => return Value.initTag(.void_value), | 2667 | .void => return Value.initTag(.void_value), |
| 2640 | .noreturn => return Value.initTag(.unreachable_value), | 2668 | .noreturn => return Value.initTag(.unreachable_value), |
| 2641 | .@"null" => return Value.initTag(.null_value), | 2669 | .@"null" => return Value.initTag(.null_value), |
| ... | @@ -2743,6 +2771,7 @@ pub const Type = extern union { | ... | @@ -2743,6 +2771,7 @@ pub const Type = extern union { |
| 2743 | .anyerror_void_error_union, | 2771 | .anyerror_void_error_union, |
| 2744 | .error_set, | 2772 | .error_set, |
| 2745 | .error_set_single, | 2773 | .error_set_single, |
| 2774 | .empty_struct, | ||
| 2746 | => return false, | 2775 | => return false, |
| 2747 | 2776 | ||
| 2748 | .c_const_pointer, | 2777 | .c_const_pointer, |
| ... | @@ -2760,6 +2789,80 @@ pub const Type = extern union { | ... | @@ -2760,6 +2789,80 @@ pub const Type = extern union { |
| 2760 | (self.isSinglePointer() and self.elemType().zigTypeTag() == .Array); | 2789 | (self.isSinglePointer() and self.elemType().zigTypeTag() == .Array); |
| 2761 | } | 2790 | } |
| 2762 | 2791 | ||
| 2792 | /// Asserts that the type is a container. (note: ErrorSet is not a container). | ||
| 2793 | pub fn getContainerScope(self: Type) *Module.Scope.Container { | ||
| 2794 | return switch (self.tag()) { | ||
| 2795 | .f16, | ||
| 2796 | .f32, | ||
| 2797 | .f64, | ||
| 2798 | .f128, | ||
| 2799 | .c_longdouble, | ||
| 2800 | .comptime_int, | ||
| 2801 | .comptime_float, | ||
| 2802 | .u8, | ||
| 2803 | .i8, | ||
| 2804 | .u16, | ||
| 2805 | .i16, | ||
| 2806 | .u32, | ||
| 2807 | .i32, | ||
| 2808 | .u64, | ||
| 2809 | .i64, | ||
| 2810 | .usize, | ||
| 2811 | .isize, | ||
| 2812 | .c_short, | ||
| 2813 | .c_ushort, | ||
| 2814 | .c_int, | ||
| 2815 | .c_uint, | ||
| 2816 | .c_long, | ||
| 2817 | .c_ulong, | ||
| 2818 | .c_longlong, | ||
| 2819 | .c_ulonglong, | ||
| 2820 | .bool, | ||
| 2821 | .type, | ||
| 2822 | .anyerror, | ||
| 2823 | .fn_noreturn_no_args, | ||
| 2824 | .fn_void_no_args, | ||
| 2825 | .fn_naked_noreturn_no_args, | ||
| 2826 | .fn_ccc_void_no_args, | ||
| 2827 | .function, | ||
| 2828 | .single_const_pointer_to_comptime_int, | ||
| 2829 | .const_slice_u8, | ||
| 2830 | .c_void, | ||
| 2831 | .void, | ||
| 2832 | .noreturn, | ||
| 2833 | .@"null", | ||
| 2834 | .@"undefined", | ||
| 2835 | .int_unsigned, | ||
| 2836 | .int_signed, | ||
| 2837 | .array, | ||
| 2838 | .array_sentinel, | ||
| 2839 | .array_u8, | ||
| 2840 | .array_u8_sentinel_0, | ||
| 2841 | .single_const_pointer, | ||
| 2842 | .single_mut_pointer, | ||
| 2843 | .many_const_pointer, | ||
| 2844 | .many_mut_pointer, | ||
| 2845 | .const_slice, | ||
| 2846 | .mut_slice, | ||
| 2847 | .optional, | ||
| 2848 | .optional_single_mut_pointer, | ||
| 2849 | .optional_single_const_pointer, | ||
| 2850 | .enum_literal, | ||
| 2851 | .error_union, | ||
| 2852 | .@"anyframe", | ||
| 2853 | .anyframe_T, | ||
| 2854 | .anyerror_void_error_union, | ||
| 2855 | .error_set, | ||
| 2856 | .error_set_single, | ||
| 2857 | .c_const_pointer, | ||
| 2858 | .c_mut_pointer, | ||
| 2859 | .pointer, | ||
| 2860 | => unreachable, | ||
| 2861 | |||
| 2862 | .empty_struct => self.cast(Type.Payload.EmptyStruct).?.scope, | ||
| 2863 | }; | ||
| 2864 | } | ||
| 2865 | |||
| 2763 | /// This enum does not directly correspond to `std.builtin.TypeId` because | 2866 | /// This enum does not directly correspond to `std.builtin.TypeId` because |
| 2764 | /// it has extra enum tags in it, as a way of using less memory. For example, | 2867 | /// it has extra enum tags in it, as a way of using less memory. For example, |
| 2765 | /// even though Zig recognizes `*align(10) i32` and `*i32` both as Pointer types | 2868 | /// even though Zig recognizes `*align(10) i32` and `*i32` both as Pointer types |
| ... | @@ -2835,6 +2938,7 @@ pub const Type = extern union { | ... | @@ -2835,6 +2938,7 @@ pub const Type = extern union { |
| 2835 | anyframe_T, | 2938 | anyframe_T, |
| 2836 | error_set, | 2939 | error_set, |
| 2837 | error_set_single, | 2940 | error_set_single, |
| 2941 | empty_struct, | ||
| 2838 | 2942 | ||
| 2839 | pub const last_no_payload_tag = Tag.const_slice_u8; | 2943 | pub const last_no_payload_tag = Tag.const_slice_u8; |
| 2840 | pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1; | 2944 | pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1; |
| ... | @@ -2942,6 +3046,14 @@ pub const Type = extern union { | ... | @@ -2942,6 +3046,14 @@ pub const Type = extern union { |
| 2942 | /// memory is owned by `Module` | 3046 | /// memory is owned by `Module` |
| 2943 | name: []const u8, | 3047 | name: []const u8, |
| 2944 | }; | 3048 | }; |
| 3049 | |||
| 3050 | /// Mostly used for namespace like structs with zero fields. | ||
| 3051 | /// Most commonly used for files. | ||
| 3052 | pub const EmptyStruct = struct { | ||
| 3053 | base: Payload = .{ .tag = .empty_struct }, | ||
| 3054 | |||
| 3055 | scope: *Module.Scope.Container, | ||
| 3056 | }; | ||
| 2945 | }; | 3057 | }; |
| 2946 | }; | 3058 | }; |
| 2947 | 3059 |
src/value.zig+15| ... | @@ -68,6 +68,7 @@ pub const Value = extern union { | ... | @@ -68,6 +68,7 @@ pub const Value = extern union { |
| 68 | one, | 68 | one, |
| 69 | void_value, | 69 | void_value, |
| 70 | unreachable_value, | 70 | unreachable_value, |
| 71 | empty_struct_value, | ||
| 71 | empty_array, | 72 | empty_array, |
| 72 | null_value, | 73 | null_value, |
| 73 | bool_true, | 74 | bool_true, |
| ... | @@ -182,6 +183,7 @@ pub const Value = extern union { | ... | @@ -182,6 +183,7 @@ pub const Value = extern union { |
| 182 | .null_value, | 183 | .null_value, |
| 183 | .bool_true, | 184 | .bool_true, |
| 184 | .bool_false, | 185 | .bool_false, |
| 186 | .empty_struct_value, | ||
| 185 | => unreachable, | 187 | => unreachable, |
| 186 | 188 | ||
| 187 | .ty => { | 189 | .ty => { |
| ... | @@ -312,6 +314,8 @@ pub const Value = extern union { | ... | @@ -312,6 +314,8 @@ pub const Value = extern union { |
| 312 | .enum_literal_type => return out_stream.writeAll("@Type(.EnumLiteral)"), | 314 | .enum_literal_type => return out_stream.writeAll("@Type(.EnumLiteral)"), |
| 313 | .anyframe_type => return out_stream.writeAll("anyframe"), | 315 | .anyframe_type => return out_stream.writeAll("anyframe"), |
| 314 | 316 | ||
| 317 | // TODO this should print `NAME{}` | ||
| 318 | .empty_struct_value => return out_stream.writeAll("struct {}{}"), | ||
| 315 | .null_value => return out_stream.writeAll("null"), | 319 | .null_value => return out_stream.writeAll("null"), |
| 316 | .undef => return out_stream.writeAll("undefined"), | 320 | .undef => return out_stream.writeAll("undefined"), |
| 317 | .zero => return out_stream.writeAll("0"), | 321 | .zero => return out_stream.writeAll("0"), |
| ... | @@ -475,6 +479,7 @@ pub const Value = extern union { | ... | @@ -475,6 +479,7 @@ pub const Value = extern union { |
| 475 | .float_128, | 479 | .float_128, |
| 476 | .enum_literal, | 480 | .enum_literal, |
| 477 | .@"error", | 481 | .@"error", |
| 482 | .empty_struct_value, | ||
| 478 | => unreachable, | 483 | => unreachable, |
| 479 | }; | 484 | }; |
| 480 | } | 485 | } |
| ... | @@ -543,6 +548,7 @@ pub const Value = extern union { | ... | @@ -543,6 +548,7 @@ pub const Value = extern union { |
| 543 | .enum_literal, | 548 | .enum_literal, |
| 544 | .error_set, | 549 | .error_set, |
| 545 | .@"error", | 550 | .@"error", |
| 551 | .empty_struct_value, | ||
| 546 | => unreachable, | 552 | => unreachable, |
| 547 | 553 | ||
| 548 | .undef => unreachable, | 554 | .undef => unreachable, |
| ... | @@ -626,6 +632,7 @@ pub const Value = extern union { | ... | @@ -626,6 +632,7 @@ pub const Value = extern union { |
| 626 | .enum_literal, | 632 | .enum_literal, |
| 627 | .error_set, | 633 | .error_set, |
| 628 | .@"error", | 634 | .@"error", |
| 635 | .empty_struct_value, | ||
| 629 | => unreachable, | 636 | => unreachable, |
| 630 | 637 | ||
| 631 | .undef => unreachable, | 638 | .undef => unreachable, |
| ... | @@ -709,6 +716,7 @@ pub const Value = extern union { | ... | @@ -709,6 +716,7 @@ pub const Value = extern union { |
| 709 | .enum_literal, | 716 | .enum_literal, |
| 710 | .error_set, | 717 | .error_set, |
| 711 | .@"error", | 718 | .@"error", |
| 719 | .empty_struct_value, | ||
| 712 | => unreachable, | 720 | => unreachable, |
| 713 | 721 | ||
| 714 | .undef => unreachable, | 722 | .undef => unreachable, |
| ... | @@ -820,6 +828,7 @@ pub const Value = extern union { | ... | @@ -820,6 +828,7 @@ pub const Value = extern union { |
| 820 | .enum_literal, | 828 | .enum_literal, |
| 821 | .error_set, | 829 | .error_set, |
| 822 | .@"error", | 830 | .@"error", |
| 831 | .empty_struct_value, | ||
| 823 | => unreachable, | 832 | => unreachable, |
| 824 | 833 | ||
| 825 | .zero, | 834 | .zero, |
| ... | @@ -907,6 +916,7 @@ pub const Value = extern union { | ... | @@ -907,6 +916,7 @@ pub const Value = extern union { |
| 907 | .enum_literal, | 916 | .enum_literal, |
| 908 | .error_set, | 917 | .error_set, |
| 909 | .@"error", | 918 | .@"error", |
| 919 | .empty_struct_value, | ||
| 910 | => unreachable, | 920 | => unreachable, |
| 911 | 921 | ||
| 912 | .zero, | 922 | .zero, |
| ... | @@ -1078,6 +1088,7 @@ pub const Value = extern union { | ... | @@ -1078,6 +1088,7 @@ pub const Value = extern union { |
| 1078 | .enum_literal, | 1088 | .enum_literal, |
| 1079 | .error_set, | 1089 | .error_set, |
| 1080 | .@"error", | 1090 | .@"error", |
| 1091 | .empty_struct_value, | ||
| 1081 | => unreachable, | 1092 | => unreachable, |
| 1082 | 1093 | ||
| 1083 | .zero, | 1094 | .zero, |
| ... | @@ -1152,6 +1163,7 @@ pub const Value = extern union { | ... | @@ -1152,6 +1163,7 @@ pub const Value = extern union { |
| 1152 | .enum_literal, | 1163 | .enum_literal, |
| 1153 | .error_set, | 1164 | .error_set, |
| 1154 | .@"error", | 1165 | .@"error", |
| 1166 | .empty_struct_value, | ||
| 1155 | => unreachable, | 1167 | => unreachable, |
| 1156 | 1168 | ||
| 1157 | .zero, | 1169 | .zero, |
| ... | @@ -1300,6 +1312,7 @@ pub const Value = extern union { | ... | @@ -1300,6 +1312,7 @@ pub const Value = extern union { |
| 1300 | .enum_literal, | 1312 | .enum_literal, |
| 1301 | .error_set, | 1313 | .error_set, |
| 1302 | .@"error", | 1314 | .@"error", |
| 1315 | .empty_struct_value, | ||
| 1303 | => unreachable, | 1316 | => unreachable, |
| 1304 | 1317 | ||
| 1305 | .ref_val => self.cast(Payload.RefVal).?.val, | 1318 | .ref_val => self.cast(Payload.RefVal).?.val, |
| ... | @@ -1383,6 +1396,7 @@ pub const Value = extern union { | ... | @@ -1383,6 +1396,7 @@ pub const Value = extern union { |
| 1383 | .enum_literal, | 1396 | .enum_literal, |
| 1384 | .error_set, | 1397 | .error_set, |
| 1385 | .@"error", | 1398 | .@"error", |
| 1399 | .empty_struct_value, | ||
| 1386 | => unreachable, | 1400 | => unreachable, |
| 1387 | 1401 | ||
| 1388 | .empty_array => unreachable, // out of bounds array index | 1402 | .empty_array => unreachable, // out of bounds array index |
| ... | @@ -1483,6 +1497,7 @@ pub const Value = extern union { | ... | @@ -1483,6 +1497,7 @@ pub const Value = extern union { |
| 1483 | .enum_literal, | 1497 | .enum_literal, |
| 1484 | .error_set, | 1498 | .error_set, |
| 1485 | .@"error", | 1499 | .@"error", |
| 1500 | .empty_struct_value, | ||
| 1486 | => false, | 1501 | => false, |
| 1487 | 1502 | ||
| 1488 | .undef => unreachable, | 1503 | .undef => unreachable, |
src/zir.zig+4| ... | @@ -161,6 +161,8 @@ pub const Inst = struct { | ... | @@ -161,6 +161,8 @@ pub const Inst = struct { |
| 161 | @"fn", | 161 | @"fn", |
| 162 | /// Returns a function type. | 162 | /// Returns a function type. |
| 163 | fntype, | 163 | fntype, |
| 164 | /// @import(operand) | ||
| 165 | import, | ||
| 164 | /// Integer literal. | 166 | /// Integer literal. |
| 165 | int, | 167 | int, |
| 166 | /// Convert an integer value to another integer type, asserting that the destination type | 168 | /// Convert an integer value to another integer type, asserting that the destination type |
| ... | @@ -315,6 +317,7 @@ pub const Inst = struct { | ... | @@ -315,6 +317,7 @@ pub const Inst = struct { |
| 315 | .ensure_err_payload_void, | 317 | .ensure_err_payload_void, |
| 316 | .anyframe_type, | 318 | .anyframe_type, |
| 317 | .bitnot, | 319 | .bitnot, |
| 320 | .import, | ||
| 318 | => UnOp, | 321 | => UnOp, |
| 319 | 322 | ||
| 320 | .add, | 323 | .add, |
| ... | @@ -489,6 +492,7 @@ pub const Inst = struct { | ... | @@ -489,6 +492,7 @@ pub const Inst = struct { |
| 489 | .error_set, | 492 | .error_set, |
| 490 | .slice, | 493 | .slice, |
| 491 | .slice_start, | 494 | .slice_start, |
| 495 | .import, | ||
| 492 | => false, | 496 | => false, |
| 493 | 497 | ||
| 494 | .@"break", | 498 | .@"break", |
src/zir_sema.zig+32| ... | @@ -134,6 +134,7 @@ pub fn analyzeInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError! | ... | @@ -134,6 +134,7 @@ pub fn analyzeInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError! |
| 134 | .error_set => return analyzeInstErrorSet(mod, scope, old_inst.castTag(.error_set).?), | 134 | .error_set => return analyzeInstErrorSet(mod, scope, old_inst.castTag(.error_set).?), |
| 135 | .slice => return analyzeInstSlice(mod, scope, old_inst.castTag(.slice).?), | 135 | .slice => return analyzeInstSlice(mod, scope, old_inst.castTag(.slice).?), |
| 136 | .slice_start => return analyzeInstSliceStart(mod, scope, old_inst.castTag(.slice_start).?), | 136 | .slice_start => return analyzeInstSliceStart(mod, scope, old_inst.castTag(.slice_start).?), |
| 137 | .import => return analyzeInstImport(mod, scope, old_inst.castTag(.import).?), | ||
| 137 | } | 138 | } |
| 138 | } | 139 | } |
| 139 | 140 | ||
| ... | @@ -1047,6 +1048,19 @@ fn analyzeInstFieldPtr(mod: *Module, scope: *Scope, fieldptr: *zir.Inst.FieldPtr | ... | @@ -1047,6 +1048,19 @@ fn analyzeInstFieldPtr(mod: *Module, scope: *Scope, fieldptr: *zir.Inst.FieldPtr |
| 1047 | .val = Value.initPayload(&ref_payload.base), | 1048 | .val = Value.initPayload(&ref_payload.base), |
| 1048 | }); | 1049 | }); |
| 1049 | }, | 1050 | }, |
| 1051 | .Struct => { | ||
| 1052 | const container_scope = child_type.getContainerScope(); | ||
| 1053 | if (mod.lookupDeclName(&container_scope.base, field_name)) |decl| { | ||
| 1054 | // TODO if !decl.is_pub and inDifferentFiles() "{} is private" | ||
| 1055 | return mod.analyzeDeclRef(scope, fieldptr.base.src, decl); | ||
| 1056 | } | ||
| 1057 | |||
| 1058 | if (&container_scope.file_scope.base == mod.root_scope) { | ||
| 1059 | return mod.fail(scope, fieldptr.base.src, "root source file has no member called '{}'", .{field_name}); | ||
| 1060 | } else { | ||
| 1061 | return mod.fail(scope, fieldptr.base.src, "container '{}' has no member called '{}'", .{ child_type, field_name }); | ||
| 1062 | } | ||
| 1063 | }, | ||
| 1050 | else => return mod.fail(scope, fieldptr.base.src, "type '{}' does not support field access", .{child_type}), | 1064 | else => return mod.fail(scope, fieldptr.base.src, "type '{}' does not support field access", .{child_type}), |
| 1051 | } | 1065 | } |
| 1052 | }, | 1066 | }, |
| ... | @@ -1190,6 +1204,24 @@ fn analyzeInstSliceStart(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) Inn | ... | @@ -1190,6 +1204,24 @@ fn analyzeInstSliceStart(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) Inn |
| 1190 | return mod.analyzeSlice(scope, inst.base.src, array_ptr, start, null, null); | 1204 | return mod.analyzeSlice(scope, inst.base.src, array_ptr, start, null, null); |
| 1191 | } | 1205 | } |
| 1192 | 1206 | ||
| 1207 | fn analyzeInstImport(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst { | ||
| 1208 | const operand = try resolveConstString(mod, scope, inst.positionals.operand); | ||
| 1209 | |||
| 1210 | const file_scope = mod.analyzeImport(scope, inst.base.src, operand) catch |err| switch (err) { | ||
| 1211 | // error.ImportOutsidePkgPath => { | ||
| 1212 | // return mod.fail(scope, inst.base.src, "import of file outside package path: '{}'", .{operand}); | ||
| 1213 | // }, | ||
| 1214 | error.FileNotFound => { | ||
| 1215 | return mod.fail(scope, inst.base.src, "unable to find '{}'", .{operand}); | ||
| 1216 | }, | ||
| 1217 | else => { | ||
| 1218 | // TODO user friendly error to string | ||
| 1219 | return mod.fail(scope, inst.base.src, "unable to open '{}': {}", .{ operand, @errorName(err) }); | ||
| 1220 | }, | ||
| 1221 | }; | ||
| 1222 | return mod.constType(scope, inst.base.src, file_scope.root_container.ty); | ||
| 1223 | } | ||
| 1224 | |||
| 1193 | fn analyzeInstShl(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerError!*Inst { | 1225 | fn analyzeInstShl(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerError!*Inst { |
| 1194 | return mod.fail(scope, inst.base.src, "TODO implement analyzeInstShl", .{}); | 1226 | return mod.fail(scope, inst.base.src, "TODO implement analyzeInstShl", .{}); |
| 1195 | } | 1227 | } |
test/stage2/test.zig+38| ... | @@ -909,6 +909,44 @@ pub fn addCases(ctx: *TestContext) !void { | ... | @@ -909,6 +909,44 @@ pub fn addCases(ctx: *TestContext) !void { |
| 909 | ); | 909 | ); |
| 910 | } | 910 | } |
| 911 | 911 | ||
| 912 | { | ||
| 913 | var case = ctx.exe("basic import", linux_x64); | ||
| 914 | case.addCompareOutput( | ||
| 915 | \\export fn _start() noreturn { | ||
| 916 | \\ @import("print.zig").print(); | ||
| 917 | \\ exit(); | ||
| 918 | \\} | ||
| 919 | \\ | ||
| 920 | \\fn exit() noreturn { | ||
| 921 | \\ asm volatile ("syscall" | ||
| 922 | \\ : | ||
| 923 | \\ : [number] "{rax}" (231), | ||
| 924 | \\ [arg1] "{rdi}" (@as(usize, 0)) | ||
| 925 | \\ : "rcx", "r11", "memory" | ||
| 926 | \\ ); | ||
| 927 | \\ unreachable; | ||
| 928 | \\} | ||
| 929 | , | ||
| 930 | "Hello, World!\n", | ||
| 931 | ); | ||
| 932 | try case.files.append(.{ | ||
| 933 | .src = | ||
| 934 | \\pub fn print() void { | ||
| 935 | \\ asm volatile ("syscall" | ||
| 936 | \\ : | ||
| 937 | \\ : [number] "{rax}" (@as(usize, 1)), | ||
| 938 | \\ [arg1] "{rdi}" (@as(usize, 1)), | ||
| 939 | \\ [arg2] "{rsi}" (@ptrToInt("Hello, World!\n")), | ||
| 940 | \\ [arg3] "{rdx}" (@as(usize, 14)) | ||
| 941 | \\ : "rcx", "r11", "memory" | ||
| 942 | \\ ); | ||
| 943 | \\ return; | ||
| 944 | \\} | ||
| 945 | , | ||
| 946 | .path = "print.zig", | ||
| 947 | }); | ||
| 948 | } | ||
| 949 | |||
| 912 | { | 950 | { |
| 913 | var case = ctx.exe("wasm function calls", wasi); | 951 | var case = ctx.exe("wasm function calls", wasi); |
| 914 | 952 |