stage2: add float values
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user