diff options
| author | g-w1 <jacoblevgw@gmail.com> | 2020-12-31 17:10:49 -0500 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2021-02-25 16:41:16 -0800 |
| commit | 153c97ac9ec8deafb0777ae424f00695c18e3bd9 (patch) | |
| tree | 4bc0b2c23e2d4844252efd98f453a2100043b14f /src/value.zig | |
| parent | 7edb204edfa41e11776ac009da5a20fb1c907f5f (diff) | |
| download | zig-153c97ac9ec8deafb0777ae424f00695c18e3bd9.tar.gz zig-153c97ac9ec8deafb0777ae424f00695c18e3bd9.zip | |
improve stage2 to allow catch at comptime:
* add error_union value tag.
* add analyzeIsErr
* add Value.isError
* add TZIR wrap_errunion_payload and wrap_errunion_err for
wrapping from T -> E!T and E -> E!T
* add anlyzeInstUnwrapErrCode and analyzeInstUnwrapErr
* add analyzeInstEnsureErrPayloadVoid:
* add wrapErrorUnion
* add comptime error comparison for tests
* tests!
Diffstat (limited to 'src/value.zig')
| -rw-r--r-- | src/value.zig | 118 |
1 files changed, 116 insertions, 2 deletions
diff --git a/src/value.zig b/src/value.zig index 50298da682..a602d08c06 100644 --- a/src/value.zig +++ b/src/value.zig @@ -102,6 +102,7 @@ pub const Value = extern union { enum_literal, error_set, @"error", + error_union, /// This is a special value that tracks a set of types that have been stored /// to an inferred allocation. It does not support any of the normal value queries. inferred_alloc, @@ -174,6 +175,7 @@ pub const Value = extern union { .ref_val, .repeated, + .error_union, => Payload.SubValue, .bytes, @@ -388,9 +390,17 @@ pub const Value = extern union { return Value{ .ptr_otherwise = &new_payload.base }; }, .@"error" => return self.copyPayloadShallow(allocator, Payload.Error), + .error_union => { + const payload = self.castTag(.error_union).?; + const new_payload = try allocator.create(Payload.SubValue); + new_payload.* = .{ + .base = payload.base, + .data = try payload.data.copy(allocator), + }; + return Value{ .ptr_otherwise = &new_payload.base }; + }, .error_set => return self.copyPayloadShallow(allocator, Payload.ErrorSet), - .inferred_alloc => unreachable, } } @@ -510,6 +520,8 @@ pub const Value = extern union { return out_stream.writeAll("}"); }, .@"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}), .inferred_alloc => return out_stream.writeAll("(inferred allocation value)"), }; } @@ -622,6 +634,7 @@ pub const Value = extern union { .float_128, .enum_literal, .@"error", + .error_union, .empty_struct_value, .inferred_alloc, => unreachable, @@ -692,6 +705,7 @@ pub const Value = extern union { .empty_array, .enum_literal, .error_set, + .error_union, .@"error", .empty_struct_value, .inferred_alloc, @@ -779,6 +793,7 @@ pub const Value = extern union { .enum_literal, .error_set, .@"error", + .error_union, .empty_struct_value, .inferred_alloc, => unreachable, @@ -865,6 +880,7 @@ pub const Value = extern union { .enum_literal, .error_set, .@"error", + .error_union, .empty_struct_value, .inferred_alloc, => unreachable, @@ -979,6 +995,7 @@ pub const Value = extern union { .enum_literal, .error_set, .@"error", + .error_union, .empty_struct_value, .inferred_alloc, => unreachable, @@ -1069,6 +1086,7 @@ pub const Value = extern union { .enum_literal, .error_set, .@"error", + .error_union, .empty_struct_value, .inferred_alloc, => unreachable, @@ -1228,6 +1246,7 @@ pub const Value = extern union { .enum_literal, .error_set, .@"error", + .error_union, .empty_struct_value, .inferred_alloc, => unreachable, @@ -1305,6 +1324,7 @@ pub const Value = extern union { .enum_literal, .error_set, .@"error", + .error_union, .empty_struct_value, .inferred_alloc, => unreachable, @@ -1543,7 +1563,10 @@ pub const Value = extern union { hasher.update(payload.name); std.hash.autoHash(&hasher, payload.value); }, - + .error_union => { + const payload = self.castTag(.error_union).?.data; + std.hash.autoHash(&hasher, payload.hash()); + }, .inferred_alloc => unreachable, } return hasher.final(); @@ -1621,6 +1644,7 @@ pub const Value = extern union { .enum_literal, .error_set, .@"error", + .error_union, .empty_struct_value, .inferred_alloc, => unreachable, @@ -1707,6 +1731,7 @@ pub const Value = extern union { .enum_literal, .error_set, .@"error", + .error_union, .empty_struct_value, .inferred_alloc, => unreachable, @@ -1810,6 +1835,7 @@ pub const Value = extern union { .enum_literal, .error_set, .@"error", + .error_union, .empty_struct_value, => false, @@ -1820,6 +1846,93 @@ pub const Value = extern union { }; } + /// Valid for all types. Asserts the value is not undefined and not unreachable. + pub fn getError(self: Value) ?[]const u8 { + return switch (self.tag()) { + .ty, + .int_type, + .u8_type, + .i8_type, + .u16_type, + .i16_type, + .u32_type, + .i32_type, + .u64_type, + .i64_type, + .usize_type, + .isize_type, + .c_short_type, + .c_ushort_type, + .c_int_type, + .c_uint_type, + .c_long_type, + .c_ulong_type, + .c_longlong_type, + .c_ulonglong_type, + .c_longdouble_type, + .f16_type, + .f32_type, + .f64_type, + .f128_type, + .c_void_type, + .bool_type, + .void_type, + .type_type, + .anyerror_type, + .comptime_int_type, + .comptime_float_type, + .noreturn_type, + .null_type, + .undefined_type, + .fn_noreturn_no_args_type, + .fn_void_no_args_type, + .fn_naked_noreturn_no_args_type, + .fn_ccc_void_no_args_type, + .single_const_pointer_to_comptime_int_type, + .const_slice_u8_type, + .enum_literal_type, + .anyframe_type, + .zero, + .one, + .null_value, + .empty_array, + .bool_true, + .bool_false, + .function, + .extern_fn, + .variable, + .int_u64, + .int_i64, + .int_big_positive, + .int_big_negative, + .ref_val, + .decl_ref, + .elem_ptr, + .bytes, + .repeated, + .float_16, + .float_32, + .float_64, + .float_128, + .void_value, + .enum_literal, + .error_set, + .empty_struct_value, + => null, + + .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, + .undef => unreachable, + .unreachable_value => unreachable, + .inferred_alloc => unreachable, + }; + } /// Valid for all types. Asserts the value is not undefined. pub fn isFloat(self: Value) bool { return switch (self.tag()) { @@ -1908,6 +2021,7 @@ pub const Value = extern union { .void_value, .enum_literal, .@"error", + .error_union, .empty_struct_value, .null_value, => false, |
