authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-02-24 22:27:54-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-02-24 22:28:37-07:00
log27eb42c15e4e9ab547eaf02cca8810cc0e10e6bf
tree83cd40198ef1f55946163766a04fe9202a510206
parentadb746a7017ba6f91974d5e940bc8a8f64bb45f5

Sema: implement tupleFieldVal, fix comptime elem_ptr


9 files changed, 90 insertions(+), 33 deletions(-)

src/Sema.zig+44
...@@ -14360,6 +14360,10 @@ fn structFieldVal(...@@ -14360,6 +14360,10 @@ fn structFieldVal(
14360 assert(unresolved_struct_ty.zigTypeTag() == .Struct);14360 assert(unresolved_struct_ty.zigTypeTag() == .Struct);
1436114361
14362 const struct_ty = try sema.resolveTypeFields(block, src, unresolved_struct_ty);14362 const struct_ty = try sema.resolveTypeFields(block, src, unresolved_struct_ty);
14363 if (struct_ty.isTuple()) {
14364 return sema.tupleFieldVal(block, src, struct_byval, field_name, field_name_src, struct_ty);
14365 }
14366
14363 const struct_obj = struct_ty.castTag(.@"struct").?.data;14367 const struct_obj = struct_ty.castTag(.@"struct").?.data;
1436414368
14365 const field_index_usize = struct_obj.fields.getIndex(field_name) orelse14369 const field_index_usize = struct_obj.fields.getIndex(field_name) orelse
...@@ -14381,6 +14385,46 @@ fn structFieldVal(...@@ -14381,6 +14385,46 @@ fn structFieldVal(
14381 return block.addStructFieldVal(struct_byval, field_index, field.ty);14385 return block.addStructFieldVal(struct_byval, field_index, field.ty);
14382}14386}
1438314387
14388fn tupleFieldVal(
14389 sema: *Sema,
14390 block: *Block,
14391 src: LazySrcLoc,
14392 tuple_byval: Air.Inst.Ref,
14393 field_name: []const u8,
14394 field_name_src: LazySrcLoc,
14395 tuple_ty: Type,
14396) CompileError!Air.Inst.Ref {
14397 const tuple = tuple_ty.castTag(.tuple).?.data;
14398
14399 if (mem.eql(u8, field_name, "len")) {
14400 return sema.addIntUnsigned(Type.usize, tuple.types.len);
14401 }
14402
14403 const field_index = std.fmt.parseUnsigned(u32, field_name, 10) catch |err| {
14404 return sema.fail(block, field_name_src, "tuple {} has no such field '{s}': {s}", .{
14405 tuple_ty, field_name, @errorName(err),
14406 });
14407 };
14408
14409 const field_ty = tuple.types[field_index];
14410
14411 if (tuple.values[field_index].tag() != .unreachable_value) {
14412 return sema.addConstant(field_ty, tuple.values[field_index]);
14413 }
14414
14415 if (try sema.resolveMaybeUndefVal(block, src, tuple_byval)) |tuple_val| {
14416 if (tuple_val.isUndef()) return sema.addConstUndef(field_ty);
14417 if ((try sema.typeHasOnePossibleValue(block, src, field_ty))) |opv| {
14418 return sema.addConstant(field_ty, opv);
14419 }
14420 const field_values = tuple_val.castTag(.@"struct").?.data;
14421 return sema.addConstant(field_ty, field_values[field_index]);
14422 }
14423
14424 try sema.requireRuntimeBlock(block, src);
14425 return block.addStructFieldVal(tuple_byval, field_index, field_ty);
14426}
14427
14384fn unionFieldPtr(14428fn unionFieldPtr(
14385 sema: *Sema,14429 sema: *Sema,
14386 block: *Block,14430 block: *Block,
src/value.zig+29-11
...@@ -1851,7 +1851,13 @@ pub const Value = extern union {...@@ -1851,7 +1851,13 @@ pub const Value = extern union {
18511851
1852 return eql(a_payload.ptr, b_payload.ptr, ptr_ty);1852 return eql(a_payload.ptr, b_payload.ptr, ptr_ty);
1853 },1853 },
1854 .elem_ptr => @panic("TODO: Implement more pointer eql cases"),1854 .elem_ptr => {
1855 const a_payload = a.castTag(.elem_ptr).?.data;
1856 const b_payload = b.castTag(.elem_ptr).?.data;
1857 if (a_payload.index != b_payload.index) return false;
1858
1859 return eql(a_payload.array_ptr, b_payload.array_ptr, ty);
1860 },
1855 .field_ptr => {1861 .field_ptr => {
1856 const a_payload = a.castTag(.field_ptr).?.data;1862 const a_payload = a.castTag(.field_ptr).?.data;
1857 const b_payload = b.castTag(.field_ptr).?.data;1863 const b_payload = b.castTag(.field_ptr).?.data;
...@@ -2327,21 +2333,33 @@ pub const Value = extern union {...@@ -2327,21 +2333,33 @@ pub const Value = extern union {
2327 }2333 }
23282334
2329 /// Returns a pointer to the element value at the index.2335 /// Returns a pointer to the element value at the index.
2330 pub fn elemPtr(self: Value, allocator: Allocator, index: usize) !Value {2336 pub fn elemPtr(val: Value, arena: Allocator, index: usize) Allocator.Error!Value {
2331 switch (self.tag()) {2337 switch (val.tag()) {
2332 .elem_ptr => {2338 .elem_ptr => {
2333 const elem_ptr = self.castTag(.elem_ptr).?.data;2339 const elem_ptr = val.castTag(.elem_ptr).?.data;
2334 return Tag.elem_ptr.create(allocator, .{2340 return Tag.elem_ptr.create(arena, .{
2335 .array_ptr = elem_ptr.array_ptr,2341 .array_ptr = elem_ptr.array_ptr,
2336 .index = elem_ptr.index + index,2342 .index = elem_ptr.index + index,
2337 });2343 });
2338 },2344 },
2339 .slice => return Tag.elem_ptr.create(allocator, .{2345 .slice => {
2340 .array_ptr = self.castTag(.slice).?.data.ptr,2346 const ptr_val = val.castTag(.slice).?.data.ptr;
2341 .index = index,2347 switch (ptr_val.tag()) {
2342 }),2348 .elem_ptr => {
2343 else => return Tag.elem_ptr.create(allocator, .{2349 const elem_ptr = ptr_val.castTag(.elem_ptr).?.data;
2344 .array_ptr = self,2350 return Tag.elem_ptr.create(arena, .{
2351 .array_ptr = elem_ptr.array_ptr,
2352 .index = elem_ptr.index + index,
2353 });
2354 },
2355 else => return Tag.elem_ptr.create(arena, .{
2356 .array_ptr = ptr_val,
2357 .index = index,
2358 }),
2359 }
2360 },
2361 else => return Tag.elem_ptr.create(arena, .{
2362 .array_ptr = val,
2345 .index = index,2363 .index = index,
2346 }),2364 }),
2347 }2365 }
test/behavior/basic.zig+5-5
...@@ -691,8 +691,6 @@ test "string escapes" {...@@ -691,8 +691,6 @@ test "string escapes" {
691}691}
692692
693test "explicit cast optional pointers" {693test "explicit cast optional pointers" {
694 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
695
696 const a: ?*i32 = undefined;694 const a: ?*i32 = undefined;
697 const b: ?*f32 = @ptrCast(?*f32, a);695 const b: ?*f32 = @ptrCast(?*f32, a);
698 _ = b;696 _ = b;
...@@ -735,7 +733,6 @@ test "string concatenation" {...@@ -735,7 +733,6 @@ test "string concatenation" {
735}733}
736734
737test "thread local variable" {735test "thread local variable" {
738 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
739 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO736 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
740737
741 const S = struct {738 const S = struct {
...@@ -746,7 +743,11 @@ test "thread local variable" {...@@ -746,7 +743,11 @@ test "thread local variable" {
746}743}
747744
748test "result location is optional inside error union" {745test "result location is optional inside error union" {
749 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO746 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
747 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
748 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
749 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
750 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
750751
751 const x = maybe(true) catch unreachable;752 const x = maybe(true) catch unreachable;
752 try expect(x.? == 42);753 try expect(x.? == 42);
...@@ -760,7 +761,6 @@ fn maybe(x: bool) anyerror!?u32 {...@@ -760,7 +761,6 @@ fn maybe(x: bool) anyerror!?u32 {
760}761}
761762
762test "pointer to thread local array" {763test "pointer to thread local array" {
763 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
764 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO764 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
765765
766 const s = "Hello world";766 const s = "Hello world";
test/behavior/defer.zig+3-1
...@@ -97,7 +97,9 @@ fn runSomeErrorDefers(x: bool) !bool {...@@ -97,7 +97,9 @@ fn runSomeErrorDefers(x: bool) !bool {
97}97}
9898
99test "mixing normal and error defers" {99test "mixing normal and error defers" {
100 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO100 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
101 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
102 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
101103
102 try expect(runSomeErrorDefers(true) catch unreachable);104 try expect(runSomeErrorDefers(true) catch unreachable);
103 try expect(result[0] == 'c');105 try expect(result[0] == 'c');
test/behavior/eval.zig+1-5
...@@ -553,8 +553,6 @@ var simple_struct = SimpleStruct{ .field = 1234 };...@@ -553,8 +553,6 @@ var simple_struct = SimpleStruct{ .field = 1234 };
553const bound_fn = simple_struct.method;553const bound_fn = simple_struct.method;
554554
555test "ptr to local array argument at comptime" {555test "ptr to local array argument at comptime" {
556 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
557
558 comptime {556 comptime {
559 var bytes: [10]u8 = undefined;557 var bytes: [10]u8 = undefined;
560 modifySomeBytes(bytes[0..]);558 modifySomeBytes(bytes[0..]);
...@@ -591,8 +589,6 @@ fn testCompTimeUIntComparisons(x: u32) void {...@@ -591,8 +589,6 @@ fn testCompTimeUIntComparisons(x: u32) void {
591const hi1 = "hi";589const hi1 = "hi";
592const hi2 = hi1;590const hi2 = hi1;
593test "const global shares pointer with other same one" {591test "const global shares pointer with other same one" {
594 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
595
596 try assertEqualPtrs(&hi1[0], &hi2[0]);592 try assertEqualPtrs(&hi1[0], &hi2[0]);
597 comptime try expect(&hi1[0] == &hi2[0]);593 comptime try expect(&hi1[0] == &hi2[0]);
598}594}
...@@ -704,7 +700,7 @@ fn loopNTimes(comptime n: usize) void {...@@ -704,7 +700,7 @@ fn loopNTimes(comptime n: usize) void {
704}700}
705701
706test "variable inside inline loop that has different types on different iterations" {702test "variable inside inline loop that has different types on different iterations" {
707 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO703 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
708704
709 try testVarInsideInlineLoop(.{ true, @as(u32, 42) });705 try testVarInsideInlineLoop(.{ true, @as(u32, 42) });
710}706}
test/behavior/optional.zig+3-1
...@@ -235,7 +235,9 @@ test "assigning to an unwrapped optional field in an inline loop" {...@@ -235,7 +235,9 @@ test "assigning to an unwrapped optional field in an inline loop" {
235}235}
236236
237test "coerce an anon struct literal to optional struct" {237test "coerce an anon struct literal to optional struct" {
238 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO238 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
239 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
240 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
239241
240 const S = struct {242 const S = struct {
241 const Struct = struct {243 const Struct = struct {
test/behavior/pointers.zig-2
...@@ -177,8 +177,6 @@ test "implicit cast error unions with non-optional to optional pointer" {...@@ -177,8 +177,6 @@ test "implicit cast error unions with non-optional to optional pointer" {
177}177}
178178
179test "compare equality of optional and non-optional pointer" {179test "compare equality of optional and non-optional pointer" {
180 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
181
182 const a = @intToPtr(*const usize, 0x12345678);180 const a = @intToPtr(*const usize, 0x12345678);
183 const b = @intToPtr(?*usize, 0x12345678);181 const b = @intToPtr(?*usize, 0x12345678);
184 try expect(a == b);182 try expect(a == b);
test/behavior/slice.zig+2-1
...@@ -565,7 +565,8 @@ test "array concat of slices gives slice" {...@@ -565,7 +565,8 @@ test "array concat of slices gives slice" {
565}565}
566566
567test "slice bounds in comptime concatenation" {567test "slice bounds in comptime concatenation" {
568 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO568 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
569 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
569570
570 const bs = comptime blk: {571 const bs = comptime blk: {
571 const b = "........1........";572 const b = "........1........";
test/behavior/translate_c_macros.zig+3-7
...@@ -30,16 +30,12 @@ test "initializer list expression" {...@@ -30,16 +30,12 @@ test "initializer list expression" {
30}30}
3131
32test "sizeof in macros" {32test "sizeof in macros" {
33 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO33 try expect(@as(c_int, @sizeOf(u32)) == h.MY_SIZEOF(u32));
3434 try expect(@as(c_int, @sizeOf(u32)) == h.MY_SIZEOF2(u32));
35 try expectEqual(@as(c_int, @sizeOf(u32)), h.MY_SIZEOF(u32));
36 try expectEqual(@as(c_int, @sizeOf(u32)), h.MY_SIZEOF2(u32));
37}35}
3836
39test "reference to a struct type" {37test "reference to a struct type" {
40 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO38 try expect(@sizeOf(h.struct_Foo) == h.SIZE_OF_FOO);
41
42 try expectEqual(@sizeOf(h.struct_Foo), h.SIZE_OF_FOO);
43}39}
4440
45test "cast negative integer to pointer" {41test "cast negative integer to pointer" {