authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-10-04 18:00:21-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2020-10-04 18:00:21-04:00
log302a69f127ae8542f49d9cd07c7cc49f3bbd6181
tree063f062e7701e4679a0e97ad1a25021294663640
parent0e2d858d69ee1595bb58d936f83f0e0248d54d68
parent6d3858dc8a5e5d510a6c9cc972357dda551628b3
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #6295 from Vexu/stage2

Stage2: basic imports

10 files changed, 301 insertions(+), 5 deletions(-)

src/Compilation.zig+17-1
......@@ -8,6 +8,7 @@ const log = std.log.scoped(.compilation);
88const Target = std.Target;
99
1010const Value = @import("value.zig").Value;
11const Type = @import("type.zig").Type;
1112const target_util = @import("target.zig");
1213const Package = @import("Package.zig");
1314const link = @import("link.zig");
......@@ -640,15 +641,19 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
640641
641642 const root_scope = rs: {
642643 if (mem.endsWith(u8, root_pkg.root_src_path, ".zig")) {
644 const struct_payload = try gpa.create(Type.Payload.EmptyStruct);
643645 const root_scope = try gpa.create(Module.Scope.File);
646 struct_payload.* = .{ .scope = &root_scope.root_container };
644647 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),
646650 .source = .{ .unloaded = {} },
647651 .contents = .{ .not_available = {} },
648652 .status = .never_loaded,
649653 .root_container = .{
650654 .file_scope = root_scope,
651655 .decls = .{},
656 .ty = Type.initPayload(&struct_payload.base),
652657 },
653658 };
654659 break :rs &root_scope.base;
......@@ -1025,6 +1030,17 @@ pub fn update(self: *Compilation) !void {
10251030 else => |e| return e,
10261031 };
10271032 }
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 }
10281044 }
10291045 }
10301046
src/Module.zig+52-4
......@@ -70,6 +70,9 @@ deletion_set: ArrayListUnmanaged(*Decl) = .{},
7070/// Error tags and their values, tag names are duped with mod.gpa.
7171global_error_set: std.StringHashMapUnmanaged(u16) = .{},
7272
73/// Keys are fully qualified paths
74import_table: std.StringArrayHashMapUnmanaged(*Scope.File) = .{},
75
7376/// Incrementing integer used to compare against the corresponding Decl
7477/// field to determine whether a Decl's status applies to an ongoing update, or a
7578/// previous analysis.
......@@ -208,7 +211,7 @@ pub const Decl = struct {
208211 .container => {
209212 const container = @fieldParentPtr(Scope.Container, "base", self.scope);
210213 const tree = container.file_scope.contents.tree;
211 // TODO Container should have it's own decls()
214 // TODO Container should have its own decls()
212215 const decl_node = tree.root_node.decls()[self.src_index];
213216 return tree.token_locs[decl_node.firstToken()].start;
214217 },
......@@ -532,12 +535,13 @@ pub const Scope = struct {
532535
533536 /// Direct children of the file.
534537 decls: std.AutoArrayHashMapUnmanaged(*Decl, void),
535
536 // TODO implement container types and put this in a status union
537 // ty: Type
538 ty: Type,
538539
539540 pub fn deinit(self: *Container, gpa: *Allocator) void {
540541 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);
541545 self.* = undefined;
542546 }
543547
......@@ -854,6 +858,11 @@ pub fn deinit(self: *Module) void {
854858 gpa.free(entry.key);
855859 }
856860 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);
857866}
858867
859868fn freeExportList(gpa: *Allocator, export_list: []*Export) void {
......@@ -2381,6 +2390,45 @@ pub fn analyzeSlice(self: *Module, scope: *Scope, src: usize, array_ptr: *Inst,
23812390 return self.fail(scope, src, "TODO implement analysis of slice", .{});
23822391}
23832392
2393pub 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
23842432/// Asserts that lhs and rhs types are both numeric.
23852433pub fn cmpNumeric(
23862434 self: *Module,
src/astgen.zig+11
......@@ -1973,6 +1973,15 @@ fn bitCast(mod: *Module, scope: *Scope, rl: ResultLoc, call: *ast.Node.BuiltinCa
19731973 }
19741974}
19751975
1976fn 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
19761985fn builtinCall(mod: *Module, scope: *Scope, rl: ResultLoc, call: *ast.Node.BuiltinCall) InnerError!*zir.Inst {
19771986 const tree = scope.tree();
19781987 const builtin_name = tree.tokenSlice(call.builtin_token);
......@@ -1995,6 +2004,8 @@ fn builtinCall(mod: *Module, scope: *Scope, rl: ResultLoc, call: *ast.Node.Built
19952004 } else if (mem.eql(u8, builtin_name, "@breakpoint")) {
19962005 const src = tree.token_locs[call.builtin_token].start;
19972006 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));
19982009 } else {
19992010 return mod.failTok(scope, call.builtin_token, "invalid builtin function: '{}'", .{builtin_name});
20002011 }
src/main.zig+5
......@@ -1454,6 +1454,11 @@ fn buildOutputType(
14541454 cleanup_root_dir = dir;
14551455 root_pkg_memory.root_src_directory = .{ .path = p, .handle = dir };
14561456 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);
14571462 } else {
14581463 root_pkg_memory.root_src_directory = .{ .path = null, .handle = fs.cwd() };
14591464 root_pkg_memory.root_src_path = src_path;
src/test.zig+15
......@@ -56,6 +56,12 @@ pub const TestContext = struct {
5656 },
5757 };
5858
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
5965 pub const TestType = enum {
6066 Zig,
6167 ZIR,
......@@ -78,6 +84,8 @@ pub const TestContext = struct {
7884 extension: TestType,
7985 cbe: bool = false,
8086
87 files: std.ArrayList(File),
88
8189 /// Adds a subcase in which the module is updated with `src`, and the
8290 /// resulting ZIR is validated against `result`.
8391 pub fn addTransform(self: *Case, src: [:0]const u8, result: [:0]const u8) void {
......@@ -156,6 +164,7 @@ pub const TestContext = struct {
156164 .updates = std.ArrayList(Update).init(ctx.cases.allocator),
157165 .output_mode = .Exe,
158166 .extension = T,
167 .files = std.ArrayList(File).init(ctx.cases.allocator),
159168 }) catch unreachable;
160169 return &ctx.cases.items[ctx.cases.items.len - 1];
161170 }
......@@ -182,6 +191,7 @@ pub const TestContext = struct {
182191 .updates = std.ArrayList(Update).init(ctx.cases.allocator),
183192 .output_mode = .Obj,
184193 .extension = T,
194 .files = std.ArrayList(File).init(ctx.cases.allocator),
185195 }) catch unreachable;
186196 return &ctx.cases.items[ctx.cases.items.len - 1];
187197 }
......@@ -204,6 +214,7 @@ pub const TestContext = struct {
204214 .output_mode = .Obj,
205215 .extension = T,
206216 .cbe = true,
217 .files = std.ArrayList(File).init(ctx.cases.allocator),
207218 }) catch unreachable;
208219 return &ctx.cases.items[ctx.cases.items.len - 1];
209220 }
......@@ -505,6 +516,10 @@ pub const TestContext = struct {
505516 });
506517 defer comp.destroy();
507518
519 for (case.files.items) |file| {
520 try tmp.dir.writeFile(file.path, file.src);
521 }
522
508523 for (case.updates.items) |update, update_index| {
509524 var update_node = root_node.start("update", 3);
510525 update_node.activate();
src/type.zig+112
......@@ -89,6 +89,8 @@ pub const Type = extern union {
8989 .anyerror_void_error_union, .error_union => return .ErrorUnion,
9090
9191 .anyframe_T, .@"anyframe" => return .AnyFrame,
92
93 .empty_struct => return .Struct,
9294 }
9395 }
9496
......@@ -439,6 +441,7 @@ pub const Type = extern union {
439441 },
440442 .error_set => return self.copyPayloadShallow(allocator, Payload.ErrorSet),
441443 .error_set_single => return self.copyPayloadShallow(allocator, Payload.ErrorSetSingle),
444 .empty_struct => return self.copyPayloadShallow(allocator, Payload.EmptyStruct),
442445 }
443446 }
444447
......@@ -505,6 +508,8 @@ pub const Type = extern union {
505508 .@"null" => return out_stream.writeAll("@Type(.Null)"),
506509 .@"undefined" => return out_stream.writeAll("@Type(.Undefined)"),
507510
511 // TODO this should print the structs name
512 .empty_struct => return out_stream.writeAll("struct {}"),
508513 .@"anyframe" => return out_stream.writeAll("anyframe"),
509514 .anyerror_void_error_union => return out_stream.writeAll("anyerror!void"),
510515 .const_slice_u8 => return out_stream.writeAll("[]const u8"),
......@@ -788,6 +793,7 @@ pub const Type = extern union {
788793 .@"null",
789794 .@"undefined",
790795 .enum_literal,
796 .empty_struct,
791797 => false,
792798 };
793799 }
......@@ -910,6 +916,7 @@ pub const Type = extern union {
910916 .@"null",
911917 .@"undefined",
912918 .enum_literal,
919 .empty_struct,
913920 => unreachable,
914921 };
915922 }
......@@ -932,6 +939,7 @@ pub const Type = extern union {
932939 .@"undefined" => unreachable,
933940 .enum_literal => unreachable,
934941 .single_const_pointer_to_comptime_int => unreachable,
942 .empty_struct => unreachable,
935943
936944 .u8,
937945 .i8,
......@@ -1107,6 +1115,7 @@ pub const Type = extern union {
11071115 .anyerror_void_error_union,
11081116 .error_set,
11091117 .error_set_single,
1118 .empty_struct,
11101119 => false,
11111120
11121121 .single_const_pointer,
......@@ -1181,6 +1190,7 @@ pub const Type = extern union {
11811190 .anyerror_void_error_union,
11821191 .error_set,
11831192 .error_set_single,
1193 .empty_struct,
11841194 => false,
11851195
11861196 .const_slice,
......@@ -1252,6 +1262,7 @@ pub const Type = extern union {
12521262 .anyerror_void_error_union,
12531263 .error_set,
12541264 .error_set_single,
1265 .empty_struct,
12551266 => false,
12561267
12571268 .single_const_pointer,
......@@ -1332,6 +1343,7 @@ pub const Type = extern union {
13321343 .anyerror_void_error_union,
13331344 .error_set,
13341345 .error_set_single,
1346 .empty_struct,
13351347 => false,
13361348
13371349 .pointer => {
......@@ -1407,6 +1419,7 @@ pub const Type = extern union {
14071419 .anyerror_void_error_union,
14081420 .error_set,
14091421 .error_set_single,
1422 .empty_struct,
14101423 => false,
14111424
14121425 .pointer => {
......@@ -1524,6 +1537,7 @@ pub const Type = extern union {
15241537 .anyerror_void_error_union,
15251538 .error_set,
15261539 .error_set_single,
1540 .empty_struct,
15271541 => unreachable,
15281542
15291543 .array => self.cast(Payload.Array).?.elem_type,
......@@ -1651,6 +1665,7 @@ pub const Type = extern union {
16511665 .anyerror_void_error_union,
16521666 .error_set,
16531667 .error_set_single,
1668 .empty_struct,
16541669 => unreachable,
16551670
16561671 .array => self.cast(Payload.Array).?.len,
......@@ -1716,6 +1731,7 @@ pub const Type = extern union {
17161731 .anyerror_void_error_union,
17171732 .error_set,
17181733 .error_set_single,
1734 .empty_struct,
17191735 => unreachable,
17201736
17211737 .single_const_pointer,
......@@ -1798,6 +1814,7 @@ pub const Type = extern union {
17981814 .anyerror_void_error_union,
17991815 .error_set,
18001816 .error_set_single,
1817 .empty_struct,
18011818 => false,
18021819
18031820 .int_signed,
......@@ -1872,6 +1889,7 @@ pub const Type = extern union {
18721889 .anyerror_void_error_union,
18731890 .error_set,
18741891 .error_set_single,
1892 .empty_struct,
18751893 => false,
18761894
18771895 .int_unsigned,
......@@ -1936,6 +1954,7 @@ pub const Type = extern union {
19361954 .anyerror_void_error_union,
19371955 .error_set,
19381956 .error_set_single,
1957 .empty_struct,
19391958 => unreachable,
19401959
19411960 .int_unsigned => .{ .signed = false, .bits = self.cast(Payload.IntUnsigned).?.bits },
......@@ -2018,6 +2037,7 @@ pub const Type = extern union {
20182037 .anyerror_void_error_union,
20192038 .error_set,
20202039 .error_set_single,
2040 .empty_struct,
20212041 => false,
20222042
20232043 .usize,
......@@ -2129,6 +2149,7 @@ pub const Type = extern union {
21292149 .anyerror_void_error_union,
21302150 .error_set,
21312151 .error_set_single,
2152 .empty_struct,
21322153 => unreachable,
21332154 };
21342155 }
......@@ -2206,6 +2227,7 @@ pub const Type = extern union {
22062227 .anyerror_void_error_union,
22072228 .error_set,
22082229 .error_set_single,
2230 .empty_struct,
22092231 => unreachable,
22102232 }
22112233 }
......@@ -2282,6 +2304,7 @@ pub const Type = extern union {
22822304 .anyerror_void_error_union,
22832305 .error_set,
22842306 .error_set_single,
2307 .empty_struct,
22852308 => unreachable,
22862309 }
22872310 }
......@@ -2358,6 +2381,7 @@ pub const Type = extern union {
23582381 .anyerror_void_error_union,
23592382 .error_set,
23602383 .error_set_single,
2384 .empty_struct,
23612385 => unreachable,
23622386 };
23632387 }
......@@ -2431,6 +2455,7 @@ pub const Type = extern union {
24312455 .anyerror_void_error_union,
24322456 .error_set,
24332457 .error_set_single,
2458 .empty_struct,
24342459 => unreachable,
24352460 };
24362461 }
......@@ -2504,6 +2529,7 @@ pub const Type = extern union {
25042529 .anyerror_void_error_union,
25052530 .error_set,
25062531 .error_set_single,
2532 .empty_struct,
25072533 => unreachable,
25082534 };
25092535 }
......@@ -2577,6 +2603,7 @@ pub const Type = extern union {
25772603 .anyerror_void_error_union,
25782604 .error_set,
25792605 .error_set_single,
2606 .empty_struct,
25802607 => false,
25812608 };
25822609 }
......@@ -2636,6 +2663,7 @@ pub const Type = extern union {
26362663 .error_set_single,
26372664 => return null,
26382665
2666 .empty_struct => return Value.initTag(.empty_struct_value),
26392667 .void => return Value.initTag(.void_value),
26402668 .noreturn => return Value.initTag(.unreachable_value),
26412669 .@"null" => return Value.initTag(.null_value),
......@@ -2743,6 +2771,7 @@ pub const Type = extern union {
27432771 .anyerror_void_error_union,
27442772 .error_set,
27452773 .error_set_single,
2774 .empty_struct,
27462775 => return false,
27472776
27482777 .c_const_pointer,
......@@ -2760,6 +2789,80 @@ pub const Type = extern union {
27602789 (self.isSinglePointer() and self.elemType().zigTypeTag() == .Array);
27612790 }
27622791
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
27632866 /// This enum does not directly correspond to `std.builtin.TypeId` because
27642867 /// it has extra enum tags in it, as a way of using less memory. For example,
27652868 /// even though Zig recognizes `*align(10) i32` and `*i32` both as Pointer types
......@@ -2835,6 +2938,7 @@ pub const Type = extern union {
28352938 anyframe_T,
28362939 error_set,
28372940 error_set_single,
2941 empty_struct,
28382942
28392943 pub const last_no_payload_tag = Tag.const_slice_u8;
28402944 pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1;
......@@ -2942,6 +3046,14 @@ pub const Type = extern union {
29423046 /// memory is owned by `Module`
29433047 name: []const u8,
29443048 };
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 };
29453057 };
29463058};
29473059
src/value.zig+15
......@@ -68,6 +68,7 @@ pub const Value = extern union {
6868 one,
6969 void_value,
7070 unreachable_value,
71 empty_struct_value,
7172 empty_array,
7273 null_value,
7374 bool_true,
......@@ -182,6 +183,7 @@ pub const Value = extern union {
182183 .null_value,
183184 .bool_true,
184185 .bool_false,
186 .empty_struct_value,
185187 => unreachable,
186188
187189 .ty => {
......@@ -312,6 +314,8 @@ pub const Value = extern union {
312314 .enum_literal_type => return out_stream.writeAll("@Type(.EnumLiteral)"),
313315 .anyframe_type => return out_stream.writeAll("anyframe"),
314316
317 // TODO this should print `NAME{}`
318 .empty_struct_value => return out_stream.writeAll("struct {}{}"),
315319 .null_value => return out_stream.writeAll("null"),
316320 .undef => return out_stream.writeAll("undefined"),
317321 .zero => return out_stream.writeAll("0"),
......@@ -475,6 +479,7 @@ pub const Value = extern union {
475479 .float_128,
476480 .enum_literal,
477481 .@"error",
482 .empty_struct_value,
478483 => unreachable,
479484 };
480485 }
......@@ -543,6 +548,7 @@ pub const Value = extern union {
543548 .enum_literal,
544549 .error_set,
545550 .@"error",
551 .empty_struct_value,
546552 => unreachable,
547553
548554 .undef => unreachable,
......@@ -626,6 +632,7 @@ pub const Value = extern union {
626632 .enum_literal,
627633 .error_set,
628634 .@"error",
635 .empty_struct_value,
629636 => unreachable,
630637
631638 .undef => unreachable,
......@@ -709,6 +716,7 @@ pub const Value = extern union {
709716 .enum_literal,
710717 .error_set,
711718 .@"error",
719 .empty_struct_value,
712720 => unreachable,
713721
714722 .undef => unreachable,
......@@ -820,6 +828,7 @@ pub const Value = extern union {
820828 .enum_literal,
821829 .error_set,
822830 .@"error",
831 .empty_struct_value,
823832 => unreachable,
824833
825834 .zero,
......@@ -907,6 +916,7 @@ pub const Value = extern union {
907916 .enum_literal,
908917 .error_set,
909918 .@"error",
919 .empty_struct_value,
910920 => unreachable,
911921
912922 .zero,
......@@ -1078,6 +1088,7 @@ pub const Value = extern union {
10781088 .enum_literal,
10791089 .error_set,
10801090 .@"error",
1091 .empty_struct_value,
10811092 => unreachable,
10821093
10831094 .zero,
......@@ -1152,6 +1163,7 @@ pub const Value = extern union {
11521163 .enum_literal,
11531164 .error_set,
11541165 .@"error",
1166 .empty_struct_value,
11551167 => unreachable,
11561168
11571169 .zero,
......@@ -1300,6 +1312,7 @@ pub const Value = extern union {
13001312 .enum_literal,
13011313 .error_set,
13021314 .@"error",
1315 .empty_struct_value,
13031316 => unreachable,
13041317
13051318 .ref_val => self.cast(Payload.RefVal).?.val,
......@@ -1383,6 +1396,7 @@ pub const Value = extern union {
13831396 .enum_literal,
13841397 .error_set,
13851398 .@"error",
1399 .empty_struct_value,
13861400 => unreachable,
13871401
13881402 .empty_array => unreachable, // out of bounds array index
......@@ -1483,6 +1497,7 @@ pub const Value = extern union {
14831497 .enum_literal,
14841498 .error_set,
14851499 .@"error",
1500 .empty_struct_value,
14861501 => false,
14871502
14881503 .undef => unreachable,
src/zir.zig+4
......@@ -161,6 +161,8 @@ pub const Inst = struct {
161161 @"fn",
162162 /// Returns a function type.
163163 fntype,
164 /// @import(operand)
165 import,
164166 /// Integer literal.
165167 int,
166168 /// Convert an integer value to another integer type, asserting that the destination type
......@@ -315,6 +317,7 @@ pub const Inst = struct {
315317 .ensure_err_payload_void,
316318 .anyframe_type,
317319 .bitnot,
320 .import,
318321 => UnOp,
319322
320323 .add,
......@@ -489,6 +492,7 @@ pub const Inst = struct {
489492 .error_set,
490493 .slice,
491494 .slice_start,
495 .import,
492496 => false,
493497
494498 .@"break",
src/zir_sema.zig+32
......@@ -134,6 +134,7 @@ pub fn analyzeInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!
134134 .error_set => return analyzeInstErrorSet(mod, scope, old_inst.castTag(.error_set).?),
135135 .slice => return analyzeInstSlice(mod, scope, old_inst.castTag(.slice).?),
136136 .slice_start => return analyzeInstSliceStart(mod, scope, old_inst.castTag(.slice_start).?),
137 .import => return analyzeInstImport(mod, scope, old_inst.castTag(.import).?),
137138 }
138139}
139140
......@@ -1047,6 +1048,19 @@ fn analyzeInstFieldPtr(mod: *Module, scope: *Scope, fieldptr: *zir.Inst.FieldPtr
10471048 .val = Value.initPayload(&ref_payload.base),
10481049 });
10491050 },
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 },
10501064 else => return mod.fail(scope, fieldptr.base.src, "type '{}' does not support field access", .{child_type}),
10511065 }
10521066 },
......@@ -1190,6 +1204,24 @@ fn analyzeInstSliceStart(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) Inn
11901204 return mod.analyzeSlice(scope, inst.base.src, array_ptr, start, null, null);
11911205}
11921206
1207fn 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
11931225fn analyzeInstShl(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerError!*Inst {
11941226 return mod.fail(scope, inst.base.src, "TODO implement analyzeInstShl", .{});
11951227}
test/stage2/test.zig+38
......@@ -909,6 +909,44 @@ pub fn addCases(ctx: *TestContext) !void {
909909 );
910910 }
911911
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
912950 {
913951 var case = ctx.exe("wasm function calls", wasi);
914952