Skip to content

Commit

Permalink
add error_union value tag. also add analyzeIsErr and Value.isError
Browse files Browse the repository at this point in the history
  • Loading branch information
g-w1 committed Dec 31, 2020
1 parent fbf269c commit 44fd783
Show file tree
Hide file tree
Showing 2 changed files with 118 additions and 1 deletion.
9 changes: 8 additions & 1 deletion src/Module.zig
Original file line number Diff line number Diff line change
Expand Up @@ -2416,7 +2416,14 @@ pub fn analyzeIsNull(
}

pub fn analyzeIsErr(self: *Module, scope: *Scope, src: usize, operand: *Inst) InnerError!*Inst {
return self.fail(scope, src, "TODO implement analysis of iserr", .{});
const ot = operand.ty.zigTypeTag();
if (ot != .ErrorSet or ot != .ErrorUnion) return self.fail(scope, src, "expected error value or error union, found '{}'", .{ot});
if (ot == .ErrorSet) return self.constBool(scope, src, true);
if (operand.value()) |err_union| {
return self.constBool(scope, src, err_union.castTag(.error_union).?.data.isError());
}
const b = try self.requireRuntimeBlock(scope, src);
return self.addUnOp(b, src, Type.initTag(.bool), .iserr, operand);
}

pub fn analyzeSlice(self: *Module, scope: *Scope, src: usize, array_ptr: *Inst, start: *Inst, end_opt: ?*Inst, sentinel_opt: ?*Inst) InnerError!*Inst {
Expand Down
110 changes: 110 additions & 0 deletions src/value.zig
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ pub const Value = extern union {
enum_literal,
error_set,
@"error",
error_union,

pub const last_no_payload_tag = Tag.bool_false;
pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1;
Expand Down Expand Up @@ -170,6 +171,7 @@ pub const Value = extern union {

.ref_val,
.repeated,
.error_union,
=> Payload.SubValue,

.bytes,
Expand Down Expand Up @@ -383,6 +385,16 @@ pub const Value = extern union {

// memory is managed by the declaration
.error_set => return self.copyPayloadShallow(allocator, Payload.ErrorSet),

.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 };
},
}
}

Expand Down Expand Up @@ -501,6 +513,8 @@ pub const Value = extern union {
return out_stream.writeAll("}");
},
.@"error" => return out_stream.print("error.{}", .{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.castTag(.error_union).?}),
};
}

Expand Down Expand Up @@ -612,6 +626,7 @@ pub const Value = extern union {
.float_128,
.enum_literal,
.@"error",
.error_union,
.empty_struct_value,
=> unreachable,
};
Expand Down Expand Up @@ -681,6 +696,7 @@ pub const Value = extern union {
.empty_array,
.enum_literal,
.error_set,
.error_union,
.@"error",
.empty_struct_value,
=> unreachable,
Expand Down Expand Up @@ -767,6 +783,7 @@ pub const Value = extern union {
.enum_literal,
.error_set,
.@"error",
.error_union,
.empty_struct_value,
=> unreachable,

Expand Down Expand Up @@ -852,6 +869,7 @@ pub const Value = extern union {
.enum_literal,
.error_set,
.@"error",
.error_union,
.empty_struct_value,
=> unreachable,

Expand Down Expand Up @@ -965,6 +983,7 @@ pub const Value = extern union {
.enum_literal,
.error_set,
.@"error",
.error_union,
.empty_struct_value,
=> unreachable,

Expand Down Expand Up @@ -1054,6 +1073,7 @@ pub const Value = extern union {
.enum_literal,
.error_set,
.@"error",
.error_union,
.empty_struct_value,
=> unreachable,

Expand Down Expand Up @@ -1212,6 +1232,7 @@ pub const Value = extern union {
.enum_literal,
.error_set,
.@"error",
.error_union,
.empty_struct_value,
=> unreachable,

Expand Down Expand Up @@ -1288,6 +1309,7 @@ pub const Value = extern union {
.enum_literal,
.error_set,
.@"error",
.error_union,
.empty_struct_value,
=> unreachable,

Expand Down Expand Up @@ -1525,6 +1547,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());
},
}
return hasher.final();
}
Expand Down Expand Up @@ -1601,6 +1627,7 @@ pub const Value = extern union {
.enum_literal,
.error_set,
.@"error",
.error_union,
.empty_struct_value,
=> unreachable,

Expand Down Expand Up @@ -1686,6 +1713,7 @@ pub const Value = extern union {
.enum_literal,
.error_set,
.@"error",
.error_union,
.empty_struct_value,
=> unreachable,

Expand Down Expand Up @@ -1788,6 +1816,7 @@ pub const Value = extern union {
.enum_literal,
.error_set,
.@"error",
.error_union,
.empty_struct_value,
=> false,

Expand All @@ -1797,6 +1826,86 @@ pub const Value = extern union {
};
}

/// Valid for all types. Asserts the value is not undefined and not unreachable.
pub fn isError(self: Value) bool {
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,
=> false,

.error_union => self.castTag(.error_union).?.data.isError(),
.@"error" => true,
.undef => unreachable,
.unreachable_value => unreachable,
};
}
/// Valid for all types. Asserts the value is not undefined.
pub fn isFloat(self: Value) bool {
return switch (self.tag()) {
Expand Down Expand Up @@ -1884,6 +1993,7 @@ pub const Value = extern union {
.void_value,
.enum_literal,
.@"error",
.error_union,
.empty_struct_value,
.null_value,
=> false,
Expand Down

0 comments on commit 44fd783

Please sign in to comment.