aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2022-02-24 22:27:54 -0700
committerAndrew Kelley <andrew@ziglang.org>2022-02-24 22:28:37 -0700
commit27eb42c15e4e9ab547eaf02cca8810cc0e10e6bf (patch)
tree83cd40198ef1f55946163766a04fe9202a510206
parentadb746a7017ba6f91974d5e940bc8a8f64bb45f5 (diff)
downloadzig-27eb42c15e4e9ab547eaf02cca8810cc0e10e6bf.tar.gz
zig-27eb42c15e4e9ab547eaf02cca8810cc0e10e6bf.zip
Sema: implement tupleFieldVal, fix comptime elem_ptr
-rw-r--r--src/Sema.zig44
-rw-r--r--src/value.zig40
-rw-r--r--test/behavior/basic.zig10
-rw-r--r--test/behavior/defer.zig4
-rw-r--r--test/behavior/eval.zig6
-rw-r--r--test/behavior/optional.zig4
-rw-r--r--test/behavior/pointers.zig2
-rw-r--r--test/behavior/slice.zig3
-rw-r--r--test/behavior/translate_c_macros.zig10
9 files changed, 90 insertions, 33 deletions
diff --git a/src/Sema.zig b/src/Sema.zig
index 3ba9761cd8..ef9ba41bec 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -14360,6 +14360,10 @@ fn structFieldVal(
assert(unresolved_struct_ty.zigTypeTag() == .Struct);
const struct_ty = try sema.resolveTypeFields(block, src, unresolved_struct_ty);
+ if (struct_ty.isTuple()) {
+ return sema.tupleFieldVal(block, src, struct_byval, field_name, field_name_src, struct_ty);
+ }
+
const struct_obj = struct_ty.castTag(.@"struct").?.data;
const field_index_usize = struct_obj.fields.getIndex(field_name) orelse
@@ -14381,6 +14385,46 @@ fn structFieldVal(
return block.addStructFieldVal(struct_byval, field_index, field.ty);
}
+fn tupleFieldVal(
+ sema: *Sema,
+ block: *Block,
+ src: LazySrcLoc,
+ tuple_byval: Air.Inst.Ref,
+ field_name: []const u8,
+ field_name_src: LazySrcLoc,
+ tuple_ty: Type,
+) CompileError!Air.Inst.Ref {
+ const tuple = tuple_ty.castTag(.tuple).?.data;
+
+ if (mem.eql(u8, field_name, "len")) {
+ return sema.addIntUnsigned(Type.usize, tuple.types.len);
+ }
+
+ const field_index = std.fmt.parseUnsigned(u32, field_name, 10) catch |err| {
+ return sema.fail(block, field_name_src, "tuple {} has no such field '{s}': {s}", .{
+ tuple_ty, field_name, @errorName(err),
+ });
+ };
+
+ const field_ty = tuple.types[field_index];
+
+ if (tuple.values[field_index].tag() != .unreachable_value) {
+ return sema.addConstant(field_ty, tuple.values[field_index]);
+ }
+
+ if (try sema.resolveMaybeUndefVal(block, src, tuple_byval)) |tuple_val| {
+ if (tuple_val.isUndef()) return sema.addConstUndef(field_ty);
+ if ((try sema.typeHasOnePossibleValue(block, src, field_ty))) |opv| {
+ return sema.addConstant(field_ty, opv);
+ }
+ const field_values = tuple_val.castTag(.@"struct").?.data;
+ return sema.addConstant(field_ty, field_values[field_index]);
+ }
+
+ try sema.requireRuntimeBlock(block, src);
+ return block.addStructFieldVal(tuple_byval, field_index, field_ty);
+}
+
fn unionFieldPtr(
sema: *Sema,
block: *Block,
diff --git a/src/value.zig b/src/value.zig
index 0b3ad15469..4df36f79a1 100644
--- a/src/value.zig
+++ b/src/value.zig
@@ -1851,7 +1851,13 @@ pub const Value = extern union {
return eql(a_payload.ptr, b_payload.ptr, ptr_ty);
},
- .elem_ptr => @panic("TODO: Implement more pointer eql cases"),
+ .elem_ptr => {
+ const a_payload = a.castTag(.elem_ptr).?.data;
+ const b_payload = b.castTag(.elem_ptr).?.data;
+ if (a_payload.index != b_payload.index) return false;
+
+ return eql(a_payload.array_ptr, b_payload.array_ptr, ty);
+ },
.field_ptr => {
const a_payload = a.castTag(.field_ptr).?.data;
const b_payload = b.castTag(.field_ptr).?.data;
@@ -2327,21 +2333,33 @@ pub const Value = extern union {
}
/// Returns a pointer to the element value at the index.
- pub fn elemPtr(self: Value, allocator: Allocator, index: usize) !Value {
- switch (self.tag()) {
+ pub fn elemPtr(val: Value, arena: Allocator, index: usize) Allocator.Error!Value {
+ switch (val.tag()) {
.elem_ptr => {
- const elem_ptr = self.castTag(.elem_ptr).?.data;
- return Tag.elem_ptr.create(allocator, .{
+ const elem_ptr = val.castTag(.elem_ptr).?.data;
+ return Tag.elem_ptr.create(arena, .{
.array_ptr = elem_ptr.array_ptr,
.index = elem_ptr.index + index,
});
},
- .slice => return Tag.elem_ptr.create(allocator, .{
- .array_ptr = self.castTag(.slice).?.data.ptr,
- .index = index,
- }),
- else => return Tag.elem_ptr.create(allocator, .{
- .array_ptr = self,
+ .slice => {
+ const ptr_val = val.castTag(.slice).?.data.ptr;
+ switch (ptr_val.tag()) {
+ .elem_ptr => {
+ const elem_ptr = ptr_val.castTag(.elem_ptr).?.data;
+ return Tag.elem_ptr.create(arena, .{
+ .array_ptr = elem_ptr.array_ptr,
+ .index = elem_ptr.index + index,
+ });
+ },
+ else => return Tag.elem_ptr.create(arena, .{
+ .array_ptr = ptr_val,
+ .index = index,
+ }),
+ }
+ },
+ else => return Tag.elem_ptr.create(arena, .{
+ .array_ptr = val,
.index = index,
}),
}
diff --git a/test/behavior/basic.zig b/test/behavior/basic.zig
index 024e24e400..304b4a83f7 100644
--- a/test/behavior/basic.zig
+++ b/test/behavior/basic.zig
@@ -691,8 +691,6 @@ test "string escapes" {
}
test "explicit cast optional pointers" {
- if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
-
const a: ?*i32 = undefined;
const b: ?*f32 = @ptrCast(?*f32, a);
_ = b;
@@ -735,7 +733,6 @@ test "string concatenation" {
}
test "thread local variable" {
- if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
const S = struct {
@@ -746,7 +743,11 @@ test "thread local variable" {
}
test "result location is optional inside error union" {
- if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
const x = maybe(true) catch unreachable;
try expect(x.? == 42);
@@ -760,7 +761,6 @@ fn maybe(x: bool) anyerror!?u32 {
}
test "pointer to thread local array" {
- if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
const s = "Hello world";
diff --git a/test/behavior/defer.zig b/test/behavior/defer.zig
index a9d363ddd1..360d6e14bb 100644
--- a/test/behavior/defer.zig
+++ b/test/behavior/defer.zig
@@ -97,7 +97,9 @@ fn runSomeErrorDefers(x: bool) !bool {
}
test "mixing normal and error defers" {
- if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
try expect(runSomeErrorDefers(true) catch unreachable);
try expect(result[0] == 'c');
diff --git a/test/behavior/eval.zig b/test/behavior/eval.zig
index 40e2377aea..a3313011a3 100644
--- a/test/behavior/eval.zig
+++ b/test/behavior/eval.zig
@@ -553,8 +553,6 @@ var simple_struct = SimpleStruct{ .field = 1234 };
const bound_fn = simple_struct.method;
test "ptr to local array argument at comptime" {
- if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
-
comptime {
var bytes: [10]u8 = undefined;
modifySomeBytes(bytes[0..]);
@@ -591,8 +589,6 @@ fn testCompTimeUIntComparisons(x: u32) void {
const hi1 = "hi";
const hi2 = hi1;
test "const global shares pointer with other same one" {
- if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
-
try assertEqualPtrs(&hi1[0], &hi2[0]);
comptime try expect(&hi1[0] == &hi2[0]);
}
@@ -704,7 +700,7 @@ fn loopNTimes(comptime n: usize) void {
}
test "variable inside inline loop that has different types on different iterations" {
- if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
try testVarInsideInlineLoop(.{ true, @as(u32, 42) });
}
diff --git a/test/behavior/optional.zig b/test/behavior/optional.zig
index 33d3b6c268..fdef0cfa96 100644
--- a/test/behavior/optional.zig
+++ b/test/behavior/optional.zig
@@ -235,7 +235,9 @@ test "assigning to an unwrapped optional field in an inline loop" {
}
test "coerce an anon struct literal to optional struct" {
- if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
const S = struct {
const Struct = struct {
diff --git a/test/behavior/pointers.zig b/test/behavior/pointers.zig
index 2832dd01d3..d3d2188b12 100644
--- a/test/behavior/pointers.zig
+++ b/test/behavior/pointers.zig
@@ -177,8 +177,6 @@ test "implicit cast error unions with non-optional to optional pointer" {
}
test "compare equality of optional and non-optional pointer" {
- if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
-
const a = @intToPtr(*const usize, 0x12345678);
const b = @intToPtr(?*usize, 0x12345678);
try expect(a == b);
diff --git a/test/behavior/slice.zig b/test/behavior/slice.zig
index 01d132df54..e746535d97 100644
--- a/test/behavior/slice.zig
+++ b/test/behavior/slice.zig
@@ -565,7 +565,8 @@ test "array concat of slices gives slice" {
}
test "slice bounds in comptime concatenation" {
- if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
const bs = comptime blk: {
const b = "........1........";
diff --git a/test/behavior/translate_c_macros.zig b/test/behavior/translate_c_macros.zig
index be66e75b9d..a67d315ffc 100644
--- a/test/behavior/translate_c_macros.zig
+++ b/test/behavior/translate_c_macros.zig
@@ -30,16 +30,12 @@ test "initializer list expression" {
}
test "sizeof in macros" {
- if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
-
- try expectEqual(@as(c_int, @sizeOf(u32)), h.MY_SIZEOF(u32));
- try expectEqual(@as(c_int, @sizeOf(u32)), h.MY_SIZEOF2(u32));
+ try expect(@as(c_int, @sizeOf(u32)) == h.MY_SIZEOF(u32));
+ try expect(@as(c_int, @sizeOf(u32)) == h.MY_SIZEOF2(u32));
}
test "reference to a struct type" {
- if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
-
- try expectEqual(@sizeOf(h.struct_Foo), h.SIZE_OF_FOO);
+ try expect(@sizeOf(h.struct_Foo) == h.SIZE_OF_FOO);
}
test "cast negative integer to pointer" {