authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-07-20 18:11:40+03:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-07-21 22:29:28+03:00
loge77ca6af7083da6723dfeb83d3788ebf7012c64e
treefdf8b0e08297123cc911e457901c83c43694639a
parentfd2f034e31bb7b2f8c671158a61473222b5cb332
signaturelock-open Commit is signed but in an unrecognized format.

stage2: add float values


1 files changed, 144 insertions(+), 17 deletions(-)

src-self-hosted/value.zig+144-17
......@@ -80,6 +80,11 @@ pub const Value = extern union {
8080 elem_ptr,
8181 bytes,
8282 repeated, // the value is a value repeated some number of times
83 float,
84 float_16,
85 float_32,
86 float_64,
87 float_128,
8388
8489 pub const last_no_payload_tag = Tag.bool_false;
8590 pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1;
......@@ -213,6 +218,10 @@ pub const Value = extern union {
213218 };
214219 return Value{ .ptr_otherwise = &new_payload.base };
215220 },
221 .float_16 => return self.copyPayloadShallow(allocator, Payload.Float_16),
222 .float_32 => return self.copyPayloadShallow(allocator, Payload.Float_32),
223 .float_64 => return self.copyPayloadShallow(allocator, Payload.Float_64),
224 .float_128, .float => return self.copyPayloadShallow(allocator, Payload.Float_128),
216225 }
217226 }
218227
......@@ -300,6 +309,10 @@ pub const Value = extern union {
300309 try out_stream.writeAll("(repeated) ");
301310 val = val.cast(Payload.Repeated).?.val;
302311 },
312 .float_16 => return out_stream.print("{}", .{val.cast(Payload.Float_16).?.val}),
313 .float_32 => return out_stream.print("{}", .{val.cast(Payload.Float_32).?.val}),
314 .float_64 => return out_stream.print("{}", .{val.cast(Payload.Float_64).?.val}),
315 .float_128, .float => return out_stream.print("{}", .{val.cast(Payload.Float_128).?.val}),
303316 };
304317 }
305318
......@@ -380,6 +393,11 @@ pub const Value = extern union {
380393 .elem_ptr,
381394 .bytes,
382395 .repeated,
396 .float,
397 .float_16,
398 .float_32,
399 .float_64,
400 .float_128,
383401 => unreachable,
384402 };
385403 }
......@@ -435,6 +453,11 @@ pub const Value = extern union {
435453 .bytes,
436454 .undef,
437455 .repeated,
456 .float,
457 .float_16,
458 .float_32,
459 .float_64,
460 .float_128,
438461 => unreachable,
439462
440463 .the_one_possible_value, // An integer with one possible value is always zero.
......@@ -502,6 +525,11 @@ pub const Value = extern union {
502525 .bytes,
503526 .undef,
504527 .repeated,
528 .float,
529 .float_16,
530 .float_32,
531 .float_64,
532 .float_128,
505533 => unreachable,
506534
507535 .zero,
......@@ -518,6 +546,25 @@ pub const Value = extern union {
518546 }
519547 }
520548
549 pub fn toBool(self: Value) bool {
550 return switch (self.tag()) {
551 .bool_true => true,
552 .bool_false, .zero => false,
553 else => unreachable,
554 };
555 }
556
557 /// Asserts that the value is a float.
558 pub fn toF128(self: Value) f128 {
559 return switch (self.tag()) {
560 .float_16 => self.cast(Payload.Float_16).?.val,
561 .float_32 => self.cast(Payload.Float_32).?.val,
562 .float_64 => self.cast(Payload.Float_64).?.val,
563 .float_128, .float => self.cast(Payload.Float_128).?.val,
564 else => unreachable,
565 };
566 }
567
521568 /// Asserts the value is an integer and not undefined.
522569 /// Returns the number of bits the value requires to represent stored in twos complement form.
523570 pub fn intBitCountTwosComp(self: Value) usize {
......@@ -570,6 +617,11 @@ pub const Value = extern union {
570617 .bytes,
571618 .undef,
572619 .repeated,
620 .float,
621 .float_16,
622 .float_32,
623 .float_64,
624 .float_128,
573625 => unreachable,
574626
575627 .the_one_possible_value, // an integer with one possible value is always zero
......@@ -642,6 +694,11 @@ pub const Value = extern union {
642694 .elem_ptr,
643695 .bytes,
644696 .repeated,
697 .float,
698 .float_16,
699 .float_32,
700 .float_64,
701 .float_128,
645702 => unreachable,
646703
647704 .zero,
......@@ -762,11 +819,17 @@ pub const Value = extern union {
762819 => unreachable,
763820
764821 .zero => false,
822
823 .float_16 => @rem(self.cast(Payload.Float_16).?.val, 1) != 0,
824 .float_32 => @rem(self.cast(Payload.Float_32).?.val, 1) != 0,
825 .float_64 => @rem(self.cast(Payload.Float_64).?.val, 1) != 0,
826 // .float_128, .float => @rem(self.cast(Payload.Float_128).?.val, 1) != 0,
827 .float_128, .float => @panic("TODO lld: error: undefined symbol: fmodl"),
765828 };
766829 }
767830
768831 pub fn orderAgainstZero(lhs: Value) std.math.Order {
769 switch (lhs.tag()) {
832 return switch (lhs.tag()) {
770833 .ty,
771834 .u8_type,
772835 .i8_type,
......@@ -820,15 +883,20 @@ pub const Value = extern union {
820883 .zero,
821884 .the_one_possible_value, // an integer with one possible value is always zero
822885 .bool_false,
823 => return .eq,
886 => .eq,
824887
825 .bool_true => return .gt,
888 .bool_true => .gt,
826889
827 .int_u64 => return std.math.order(lhs.cast(Payload.Int_u64).?.int, 0),
828 .int_i64 => return std.math.order(lhs.cast(Payload.Int_i64).?.int, 0),
829 .int_big_positive => return lhs.cast(Payload.IntBigPositive).?.asBigInt().orderAgainstScalar(0),
830 .int_big_negative => return lhs.cast(Payload.IntBigNegative).?.asBigInt().orderAgainstScalar(0),
831 }
890 .int_u64 => std.math.order(lhs.cast(Payload.Int_u64).?.int, 0),
891 .int_i64 => std.math.order(lhs.cast(Payload.Int_i64).?.int, 0),
892 .int_big_positive => lhs.cast(Payload.IntBigPositive).?.asBigInt().orderAgainstScalar(0),
893 .int_big_negative => lhs.cast(Payload.IntBigNegative).?.asBigInt().orderAgainstScalar(0),
894
895 .float_16 => std.math.order(lhs.cast(Payload.Float_16).?.val, 0),
896 .float_32 => std.math.order(lhs.cast(Payload.Float_32).?.val, 0),
897 .float_64 => std.math.order(lhs.cast(Payload.Float_64).?.val, 0),
898 .float_128, .float => std.math.order(lhs.cast(Payload.Float_128).?.val, 0),
899 };
832900 }
833901
834902 /// Asserts the value is comparable.
......@@ -840,7 +908,24 @@ pub const Value = extern union {
840908 if (lhs_is_zero) return rhs.orderAgainstZero().invert();
841909 if (rhs_is_zero) return lhs.orderAgainstZero();
842910
843 // TODO floats
911 const lhs_float = lhs.isFloat();
912 const rhs_float = rhs.isFloat();
913 if (lhs_float and rhs_float) {
914 if (lhs_tag == rhs_tag) {
915 return switch (lhs.tag()) {
916 .float_16 => return std.math.order(lhs.cast(Payload.Float_16).?.val, rhs.cast(Payload.Float_16).?.val),
917 .float_32 => return std.math.order(lhs.cast(Payload.Float_32).?.val, rhs.cast(Payload.Float_32).?.val),
918 .float_64 => return std.math.order(lhs.cast(Payload.Float_64).?.val, rhs.cast(Payload.Float_64).?.val),
919 .float_128, .float => return std.math.order(lhs.cast(Payload.Float_128).?.val, rhs.cast(Payload.Float_128).?.val),
920 else => unreachable,
921 };
922 }
923 }
924 if (lhs_float or rhs_float) {
925 const lhs_f128 = lhs.toF128();
926 const rhs_f128 = rhs.toF128();
927 return std.math.order(lhs_f128, rhs_f128);
928 }
844929
845930 var lhs_bigint_space: BigIntSpace = undefined;
846931 var rhs_bigint_space: BigIntSpace = undefined;
......@@ -864,14 +949,6 @@ pub const Value = extern union {
864949 return compare(a, .eq, b);
865950 }
866951
867 pub fn toBool(self: Value) bool {
868 return switch (self.tag()) {
869 .bool_true => true,
870 .bool_false, .zero => false,
871 else => unreachable,
872 };
873 }
874
875952 /// Asserts the value is a pointer and dereferences it.
876953 /// Returns error.AnalysisFail if the pointer points to a Decl that failed semantic analysis.
877954 pub fn pointerDeref(self: Value, allocator: *Allocator) error{ AnalysisFail, OutOfMemory }!Value {
......@@ -928,6 +1005,11 @@ pub const Value = extern union {
9281005 .bytes,
9291006 .undef,
9301007 .repeated,
1008 .float,
1009 .float_16,
1010 .float_32,
1011 .float_64,
1012 .float_128,
9311013 => unreachable,
9321014
9331015 .the_one_possible_value => Value.initTag(.the_one_possible_value),
......@@ -999,6 +1081,11 @@ pub const Value = extern union {
9991081 .elem_ptr,
10001082 .ref_val,
10011083 .decl_ref,
1084 .float,
1085 .float_16,
1086 .float_32,
1087 .float_64,
1088 .float_128,
10021089 => unreachable,
10031090
10041091 .bytes => {
......@@ -1085,6 +1172,11 @@ pub const Value = extern union {
10851172 .elem_ptr,
10861173 .bytes,
10871174 .repeated,
1175 .float,
1176 .float_16,
1177 .float_32,
1178 .float_64,
1179 .float_128,
10881180 => false,
10891181
10901182 .undef => unreachable,
......@@ -1092,6 +1184,21 @@ pub const Value = extern union {
10921184 };
10931185 }
10941186
1187 /// Valid for all types. Asserts the value is not undefined.
1188 pub fn isFloat(self: Value) bool {
1189 return switch (self.tag()) {
1190 .undef => unreachable,
1191
1192 .float,
1193 .float_16,
1194 .float_32,
1195 .float_64,
1196 .float_128,
1197 => true,
1198 else => false,
1199 };
1200 }
1201
10951202 /// This type is not copyable since it may contain pointers to its inner data.
10961203 pub const Payload = struct {
10971204 tag: Tag,
......@@ -1168,6 +1275,26 @@ pub const Value = extern union {
11681275 /// is stored externally.
11691276 val: Value,
11701277 };
1278
1279 pub const Float_16 = struct {
1280 base: Payload = .{ .tag = .float_16 },
1281 val: f16,
1282 };
1283
1284 pub const Float_32 = struct {
1285 base: Payload = .{ .tag = .float_32 },
1286 val: f32,
1287 };
1288
1289 pub const Float_64 = struct {
1290 base: Payload = .{ .tag = .float_64 },
1291 val: f64,
1292 };
1293
1294 pub const Float_128 = struct {
1295 base: Payload = .{ .tag = .float_128 },
1296 val: f128,
1297 };
11711298 };
11721299
11731300 /// Big enough to fit any non-BigInt value