stage2: add float values

This commit is contained in:
Vexu
2020-07-20 18:11:40 +03:00
parent fd2f034e31
commit e77ca6af70

View File

@@ -80,6 +80,11 @@ pub const Value = extern union {
elem_ptr,
bytes,
repeated, // the value is a value repeated some number of times
float,
float_16,
float_32,
float_64,
float_128,
pub const last_no_payload_tag = Tag.bool_false;
pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1;
@@ -213,6 +218,10 @@ pub const Value = extern union {
};
return Value{ .ptr_otherwise = &new_payload.base };
},
.float_16 => return self.copyPayloadShallow(allocator, Payload.Float_16),
.float_32 => return self.copyPayloadShallow(allocator, Payload.Float_32),
.float_64 => return self.copyPayloadShallow(allocator, Payload.Float_64),
.float_128, .float => return self.copyPayloadShallow(allocator, Payload.Float_128),
}
}
@@ -300,6 +309,10 @@ pub const Value = extern union {
try out_stream.writeAll("(repeated) ");
val = val.cast(Payload.Repeated).?.val;
},
.float_16 => return out_stream.print("{}", .{val.cast(Payload.Float_16).?.val}),
.float_32 => return out_stream.print("{}", .{val.cast(Payload.Float_32).?.val}),
.float_64 => return out_stream.print("{}", .{val.cast(Payload.Float_64).?.val}),
.float_128, .float => return out_stream.print("{}", .{val.cast(Payload.Float_128).?.val}),
};
}
@@ -380,6 +393,11 @@ pub const Value = extern union {
.elem_ptr,
.bytes,
.repeated,
.float,
.float_16,
.float_32,
.float_64,
.float_128,
=> unreachable,
};
}
@@ -435,6 +453,11 @@ pub const Value = extern union {
.bytes,
.undef,
.repeated,
.float,
.float_16,
.float_32,
.float_64,
.float_128,
=> unreachable,
.the_one_possible_value, // An integer with one possible value is always zero.
@@ -502,6 +525,11 @@ pub const Value = extern union {
.bytes,
.undef,
.repeated,
.float,
.float_16,
.float_32,
.float_64,
.float_128,
=> unreachable,
.zero,
@@ -518,6 +546,25 @@ pub const Value = extern union {
}
}
pub fn toBool(self: Value) bool {
return switch (self.tag()) {
.bool_true => true,
.bool_false, .zero => false,
else => unreachable,
};
}
/// Asserts that the value is a float.
pub fn toF128(self: Value) f128 {
return switch (self.tag()) {
.float_16 => self.cast(Payload.Float_16).?.val,
.float_32 => self.cast(Payload.Float_32).?.val,
.float_64 => self.cast(Payload.Float_64).?.val,
.float_128, .float => self.cast(Payload.Float_128).?.val,
else => unreachable,
};
}
/// Asserts the value is an integer and not undefined.
/// Returns the number of bits the value requires to represent stored in twos complement form.
pub fn intBitCountTwosComp(self: Value) usize {
@@ -570,6 +617,11 @@ pub const Value = extern union {
.bytes,
.undef,
.repeated,
.float,
.float_16,
.float_32,
.float_64,
.float_128,
=> unreachable,
.the_one_possible_value, // an integer with one possible value is always zero
@@ -642,6 +694,11 @@ pub const Value = extern union {
.elem_ptr,
.bytes,
.repeated,
.float,
.float_16,
.float_32,
.float_64,
.float_128,
=> unreachable,
.zero,
@@ -762,11 +819,17 @@ pub const Value = extern union {
=> unreachable,
.zero => false,
.float_16 => @rem(self.cast(Payload.Float_16).?.val, 1) != 0,
.float_32 => @rem(self.cast(Payload.Float_32).?.val, 1) != 0,
.float_64 => @rem(self.cast(Payload.Float_64).?.val, 1) != 0,
// .float_128, .float => @rem(self.cast(Payload.Float_128).?.val, 1) != 0,
.float_128, .float => @panic("TODO lld: error: undefined symbol: fmodl"),
};
}
pub fn orderAgainstZero(lhs: Value) std.math.Order {
switch (lhs.tag()) {
return switch (lhs.tag()) {
.ty,
.u8_type,
.i8_type,
@@ -820,15 +883,20 @@ pub const Value = extern union {
.zero,
.the_one_possible_value, // an integer with one possible value is always zero
.bool_false,
=> return .eq,
=> .eq,
.bool_true => return .gt,
.bool_true => .gt,
.int_u64 => return std.math.order(lhs.cast(Payload.Int_u64).?.int, 0),
.int_i64 => return std.math.order(lhs.cast(Payload.Int_i64).?.int, 0),
.int_big_positive => return lhs.cast(Payload.IntBigPositive).?.asBigInt().orderAgainstScalar(0),
.int_big_negative => return lhs.cast(Payload.IntBigNegative).?.asBigInt().orderAgainstScalar(0),
}
.int_u64 => std.math.order(lhs.cast(Payload.Int_u64).?.int, 0),
.int_i64 => std.math.order(lhs.cast(Payload.Int_i64).?.int, 0),
.int_big_positive => lhs.cast(Payload.IntBigPositive).?.asBigInt().orderAgainstScalar(0),
.int_big_negative => lhs.cast(Payload.IntBigNegative).?.asBigInt().orderAgainstScalar(0),
.float_16 => std.math.order(lhs.cast(Payload.Float_16).?.val, 0),
.float_32 => std.math.order(lhs.cast(Payload.Float_32).?.val, 0),
.float_64 => std.math.order(lhs.cast(Payload.Float_64).?.val, 0),
.float_128, .float => std.math.order(lhs.cast(Payload.Float_128).?.val, 0),
};
}
/// Asserts the value is comparable.
@@ -840,7 +908,24 @@ pub const Value = extern union {
if (lhs_is_zero) return rhs.orderAgainstZero().invert();
if (rhs_is_zero) return lhs.orderAgainstZero();
// TODO floats
const lhs_float = lhs.isFloat();
const rhs_float = rhs.isFloat();
if (lhs_float and rhs_float) {
if (lhs_tag == rhs_tag) {
return switch (lhs.tag()) {
.float_16 => return std.math.order(lhs.cast(Payload.Float_16).?.val, rhs.cast(Payload.Float_16).?.val),
.float_32 => return std.math.order(lhs.cast(Payload.Float_32).?.val, rhs.cast(Payload.Float_32).?.val),
.float_64 => return std.math.order(lhs.cast(Payload.Float_64).?.val, rhs.cast(Payload.Float_64).?.val),
.float_128, .float => return std.math.order(lhs.cast(Payload.Float_128).?.val, rhs.cast(Payload.Float_128).?.val),
else => unreachable,
};
}
}
if (lhs_float or rhs_float) {
const lhs_f128 = lhs.toF128();
const rhs_f128 = rhs.toF128();
return std.math.order(lhs_f128, rhs_f128);
}
var lhs_bigint_space: BigIntSpace = undefined;
var rhs_bigint_space: BigIntSpace = undefined;
@@ -864,14 +949,6 @@ pub const Value = extern union {
return compare(a, .eq, b);
}
pub fn toBool(self: Value) bool {
return switch (self.tag()) {
.bool_true => true,
.bool_false, .zero => false,
else => unreachable,
};
}
/// Asserts the value is a pointer and dereferences it.
/// Returns error.AnalysisFail if the pointer points to a Decl that failed semantic analysis.
pub fn pointerDeref(self: Value, allocator: *Allocator) error{ AnalysisFail, OutOfMemory }!Value {
@@ -928,6 +1005,11 @@ pub const Value = extern union {
.bytes,
.undef,
.repeated,
.float,
.float_16,
.float_32,
.float_64,
.float_128,
=> unreachable,
.the_one_possible_value => Value.initTag(.the_one_possible_value),
@@ -999,6 +1081,11 @@ pub const Value = extern union {
.elem_ptr,
.ref_val,
.decl_ref,
.float,
.float_16,
.float_32,
.float_64,
.float_128,
=> unreachable,
.bytes => {
@@ -1085,6 +1172,11 @@ pub const Value = extern union {
.elem_ptr,
.bytes,
.repeated,
.float,
.float_16,
.float_32,
.float_64,
.float_128,
=> false,
.undef => unreachable,
@@ -1092,6 +1184,21 @@ pub const Value = extern union {
};
}
/// Valid for all types. Asserts the value is not undefined.
pub fn isFloat(self: Value) bool {
return switch (self.tag()) {
.undef => unreachable,
.float,
.float_16,
.float_32,
.float_64,
.float_128,
=> true,
else => false,
};
}
/// This type is not copyable since it may contain pointers to its inner data.
pub const Payload = struct {
tag: Tag,
@@ -1168,6 +1275,26 @@ pub const Value = extern union {
/// is stored externally.
val: Value,
};
pub const Float_16 = struct {
base: Payload = .{ .tag = .float_16 },
val: f16,
};
pub const Float_32 = struct {
base: Payload = .{ .tag = .float_32 },
val: f32,
};
pub const Float_64 = struct {
base: Payload = .{ .tag = .float_64 },
val: f64,
};
pub const Float_128 = struct {
base: Payload = .{ .tag = .float_128 },
val: f128,
};
};
/// Big enough to fit any non-BigInt value