aboutsummaryrefslogtreecommitdiff
path: root/src/value.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2021-08-07 20:34:28 -0700
committerAndrew Kelley <andrew@ziglang.org>2021-08-07 20:34:28 -0700
commit799fedf612aa8742c446b015c12d21707a1dbec0 (patch)
tree1d9efbc4cb3f6dda9631160784a074e58d6bd479 /src/value.zig
parentf81b2531cb4904064446f84a06f6e09e4120e28a (diff)
downloadzig-799fedf612aa8742c446b015c12d21707a1dbec0.tar.gz
zig-799fedf612aa8742c446b015c12d21707a1dbec0.zip
stage2: pass some error union tests
* Value: rename `error_union` to `eu_payload` and clarify the intended usage in the doc comments. The way error unions is represented with Value is fixed to not have ambiguous values. * Fix codegen for error union constants in all the backends. * Implement the AIR instructions having to do with error unions in the LLVM backend.
Diffstat (limited to 'src/value.zig')
-rw-r--r--src/value.zig43
1 files changed, 31 insertions, 12 deletions
diff --git a/src/value.zig b/src/value.zig
index bf80c9d831..562d7171e8 100644
--- a/src/value.zig
+++ b/src/value.zig
@@ -129,7 +129,13 @@ pub const Value = extern union {
/// A specific enum tag, indicated by the field index (declaration order).
enum_field_index,
@"error",
- error_union,
+ /// When the type is error union:
+ /// * If the tag is `.@"error"`, the error union is an error.
+ /// * If the tag is `.eu_payload`, the error union is a payload.
+ /// * A nested error such as `((anyerror!T1)!T2)` in which the the outer error union
+ /// is non-error, but the inner error union is an error, is represented as
+ /// a tag of `.eu_payload`, with a sub-tag of `.@"error"`.
+ eu_payload,
/// A pointer to the payload of an error union, based on a pointer to an error union.
eu_payload_ptr,
/// An instance of a struct.
@@ -228,7 +234,7 @@ pub const Value = extern union {
=> Payload.Decl,
.repeated,
- .error_union,
+ .eu_payload,
.eu_payload_ptr,
=> Payload.SubValue,
@@ -450,7 +456,7 @@ pub const Value = extern union {
return Value{ .ptr_otherwise = &new_payload.base };
},
.bytes => return self.copyPayloadShallow(allocator, Payload.Bytes),
- .repeated, .error_union, .eu_payload_ptr => {
+ .repeated, .eu_payload, .eu_payload_ptr => {
const payload = self.cast(Payload.SubValue).?;
const new_payload = try allocator.create(Payload.SubValue);
new_payload.* = .{
@@ -642,7 +648,10 @@ pub const Value = extern union {
.float_128 => return out_stream.print("{}", .{val.castTag(.float_128).?.data}),
.@"error" => return out_stream.print("error.{s}", .{val.castTag(.@"error").?.data.name}),
// TODO to print this it should be error{ Set, Items }!T(val), but we need the type for that
- .error_union => return out_stream.print("error_union_val({})", .{val.castTag(.error_union).?.data}),
+ .eu_payload => {
+ try out_stream.writeAll("(eu_payload) ");
+ val = val.castTag(.eu_payload).?.data;
+ },
.inferred_alloc => return out_stream.writeAll("(inferred allocation value)"),
.inferred_alloc_comptime => return out_stream.writeAll("(inferred comptime allocation value)"),
.eu_payload_ptr => {
@@ -1241,7 +1250,7 @@ pub const Value = extern union {
.eu_payload_ptr => blk: {
const err_union_ptr = self.castTag(.eu_payload_ptr).?.data;
const err_union_val = (try err_union_ptr.pointerDeref(allocator)) orelse return null;
- break :blk err_union_val.castTag(.error_union).?.data;
+ break :blk err_union_val.castTag(.eu_payload).?.data;
},
.zero,
@@ -1351,16 +1360,16 @@ pub const Value = extern union {
}
/// Valid for all types. Asserts the value is not undefined and not unreachable.
+ /// Prefer `errorUnionIsPayload` to find out whether something is an error or not
+ /// because it works without having to figure out the string.
pub fn getError(self: Value) ?[]const u8 {
return switch (self.tag()) {
- .error_union => {
- const data = self.castTag(.error_union).?.data;
- return if (data.tag() == .@"error")
- data.castTag(.@"error").?.data.name
- else
- null;
- },
.@"error" => self.castTag(.@"error").?.data.name,
+ .int_u64 => @panic("TODO"),
+ .int_i64 => @panic("TODO"),
+ .int_big_positive => @panic("TODO"),
+ .int_big_negative => @panic("TODO"),
+ .one => @panic("TODO"),
.undef => unreachable,
.unreachable_value => unreachable,
.inferred_alloc => unreachable,
@@ -1369,6 +1378,16 @@ pub const Value = extern union {
else => null,
};
}
+
+ /// Assumes the type is an error union. Returns true if and only if the value is
+ /// the error union payload, not an error.
+ pub fn errorUnionIsPayload(val: Value) bool {
+ return switch (val.tag()) {
+ .eu_payload => true,
+ else => false,
+ };
+ }
+
/// Valid for all types. Asserts the value is not undefined.
pub fn isFloat(self: Value) bool {
return switch (self.tag()) {