| ... | @@ -80,6 +80,11 @@ pub const Value = extern union { | ... | @@ -80,6 +80,11 @@ pub const Value = extern union { |
| 80 | elem_ptr, | 80 | elem_ptr, |
| 81 | bytes, | 81 | bytes, |
| 82 | repeated, // the value is a value repeated some number of times | 82 | 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, |
| 83 | | 88 | |
| 84 | pub const last_no_payload_tag = Tag.bool_false; | 89 | pub const last_no_payload_tag = Tag.bool_false; |
| 85 | pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1; | 90 | pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1; |
| ... | @@ -213,6 +218,10 @@ pub const Value = extern union { | ... | @@ -213,6 +218,10 @@ pub const Value = extern union { |
| 213 | }; | 218 | }; |
| 214 | return Value{ .ptr_otherwise = &new_payload.base }; | 219 | return Value{ .ptr_otherwise = &new_payload.base }; |
| 215 | }, | 220 | }, |
| | 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), |
| 216 | } | 225 | } |
| 217 | } | 226 | } |
| 218 | | 227 | |
| ... | @@ -300,6 +309,10 @@ pub const Value = extern union { | ... | @@ -300,6 +309,10 @@ pub const Value = extern union { |
| 300 | try out_stream.writeAll("(repeated) "); | 309 | try out_stream.writeAll("(repeated) "); |
| 301 | val = val.cast(Payload.Repeated).?.val; | 310 | val = val.cast(Payload.Repeated).?.val; |
| 302 | }, | 311 | }, |
| | 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}), |
| 303 | }; | 316 | }; |
| 304 | } | 317 | } |
| 305 | | 318 | |
| ... | @@ -380,6 +393,11 @@ pub const Value = extern union { | ... | @@ -380,6 +393,11 @@ pub const Value = extern union { |
| 380 | .elem_ptr, | 393 | .elem_ptr, |
| 381 | .bytes, | 394 | .bytes, |
| 382 | .repeated, | 395 | .repeated, |
| | 396 | .float, |
| | 397 | .float_16, |
| | 398 | .float_32, |
| | 399 | .float_64, |
| | 400 | .float_128, |
| 383 | => unreachable, | 401 | => unreachable, |
| 384 | }; | 402 | }; |
| 385 | } | 403 | } |
| ... | @@ -435,6 +453,11 @@ pub const Value = extern union { | ... | @@ -435,6 +453,11 @@ pub const Value = extern union { |
| 435 | .bytes, | 453 | .bytes, |
| 436 | .undef, | 454 | .undef, |
| 437 | .repeated, | 455 | .repeated, |
| | 456 | .float, |
| | 457 | .float_16, |
| | 458 | .float_32, |
| | 459 | .float_64, |
| | 460 | .float_128, |
| 438 | => unreachable, | 461 | => unreachable, |
| 439 | | 462 | |
| 440 | .the_one_possible_value, // An integer with one possible value is always zero. | 463 | .the_one_possible_value, // An integer with one possible value is always zero. |
| ... | @@ -502,6 +525,11 @@ pub const Value = extern union { | ... | @@ -502,6 +525,11 @@ pub const Value = extern union { |
| 502 | .bytes, | 525 | .bytes, |
| 503 | .undef, | 526 | .undef, |
| 504 | .repeated, | 527 | .repeated, |
| | 528 | .float, |
| | 529 | .float_16, |
| | 530 | .float_32, |
| | 531 | .float_64, |
| | 532 | .float_128, |
| 505 | => unreachable, | 533 | => unreachable, |
| 506 | | 534 | |
| 507 | .zero, | 535 | .zero, |
| ... | @@ -518,6 +546,25 @@ pub const Value = extern union { | ... | @@ -518,6 +546,25 @@ pub const Value = extern union { |
| 518 | } | 546 | } |
| 519 | } | 547 | } |
| 520 | | 548 | |
| | 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 | |
| 521 | /// Asserts the value is an integer and not undefined. | 568 | /// Asserts the value is an integer and not undefined. |
| 522 | /// Returns the number of bits the value requires to represent stored in twos complement form. | 569 | /// Returns the number of bits the value requires to represent stored in twos complement form. |
| 523 | pub fn intBitCountTwosComp(self: Value) usize { | 570 | pub fn intBitCountTwosComp(self: Value) usize { |
| ... | @@ -570,6 +617,11 @@ pub const Value = extern union { | ... | @@ -570,6 +617,11 @@ pub const Value = extern union { |
| 570 | .bytes, | 617 | .bytes, |
| 571 | .undef, | 618 | .undef, |
| 572 | .repeated, | 619 | .repeated, |
| | 620 | .float, |
| | 621 | .float_16, |
| | 622 | .float_32, |
| | 623 | .float_64, |
| | 624 | .float_128, |
| 573 | => unreachable, | 625 | => unreachable, |
| 574 | | 626 | |
| 575 | .the_one_possible_value, // an integer with one possible value is always zero | 627 | .the_one_possible_value, // an integer with one possible value is always zero |
| ... | @@ -642,6 +694,11 @@ pub const Value = extern union { | ... | @@ -642,6 +694,11 @@ pub const Value = extern union { |
| 642 | .elem_ptr, | 694 | .elem_ptr, |
| 643 | .bytes, | 695 | .bytes, |
| 644 | .repeated, | 696 | .repeated, |
| | 697 | .float, |
| | 698 | .float_16, |
| | 699 | .float_32, |
| | 700 | .float_64, |
| | 701 | .float_128, |
| 645 | => unreachable, | 702 | => unreachable, |
| 646 | | 703 | |
| 647 | .zero, | 704 | .zero, |
| ... | @@ -762,11 +819,17 @@ pub const Value = extern union { | ... | @@ -762,11 +819,17 @@ pub const Value = extern union { |
| 762 | => unreachable, | 819 | => unreachable, |
| 763 | | 820 | |
| 764 | .zero => false, | 821 | .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"), |
| 765 | }; | 828 | }; |
| 766 | } | 829 | } |
| 767 | | 830 | |
| 768 | pub fn orderAgainstZero(lhs: Value) std.math.Order { | 831 | pub fn orderAgainstZero(lhs: Value) std.math.Order { |
| 769 | switch (lhs.tag()) { | 832 | return switch (lhs.tag()) { |
| 770 | .ty, | 833 | .ty, |
| 771 | .u8_type, | 834 | .u8_type, |
| 772 | .i8_type, | 835 | .i8_type, |
| ... | @@ -820,15 +883,20 @@ pub const Value = extern union { | ... | @@ -820,15 +883,20 @@ pub const Value = extern union { |
| 820 | .zero, | 883 | .zero, |
| 821 | .the_one_possible_value, // an integer with one possible value is always zero | 884 | .the_one_possible_value, // an integer with one possible value is always zero |
| 822 | .bool_false, | 885 | .bool_false, |
| 823 | => return .eq, | 886 | => .eq, |
| 824 | | 887 | |
| 825 | .bool_true => return .gt, | 888 | .bool_true => .gt, |
| 826 | | 889 | |
| 827 | .int_u64 => return std.math.order(lhs.cast(Payload.Int_u64).?.int, 0), | 890 | .int_u64 => std.math.order(lhs.cast(Payload.Int_u64).?.int, 0), |
| 828 | .int_i64 => return std.math.order(lhs.cast(Payload.Int_i64).?.int, 0), | 891 | .int_i64 => std.math.order(lhs.cast(Payload.Int_i64).?.int, 0), |
| 829 | .int_big_positive => return lhs.cast(Payload.IntBigPositive).?.asBigInt().orderAgainstScalar(0), | 892 | .int_big_positive => lhs.cast(Payload.IntBigPositive).?.asBigInt().orderAgainstScalar(0), |
| 830 | .int_big_negative => return lhs.cast(Payload.IntBigNegative).?.asBigInt().orderAgainstScalar(0), | 893 | .int_big_negative => lhs.cast(Payload.IntBigNegative).?.asBigInt().orderAgainstScalar(0), |
| 831 | } | 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 | }; |
| 832 | } | 900 | } |
| 833 | | 901 | |
| 834 | /// Asserts the value is comparable. | 902 | /// Asserts the value is comparable. |
| ... | @@ -840,7 +908,24 @@ pub const Value = extern union { | ... | @@ -840,7 +908,24 @@ pub const Value = extern union { |
| 840 | if (lhs_is_zero) return rhs.orderAgainstZero().invert(); | 908 | if (lhs_is_zero) return rhs.orderAgainstZero().invert(); |
| 841 | if (rhs_is_zero) return lhs.orderAgainstZero(); | 909 | if (rhs_is_zero) return lhs.orderAgainstZero(); |
| 842 | | 910 | |
| 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 | } |
| 844 | | 929 | |
| 845 | var lhs_bigint_space: BigIntSpace = undefined; | 930 | var lhs_bigint_space: BigIntSpace = undefined; |
| 846 | var rhs_bigint_space: BigIntSpace = undefined; | 931 | var rhs_bigint_space: BigIntSpace = undefined; |
| ... | @@ -864,14 +949,6 @@ pub const Value = extern union { | ... | @@ -864,14 +949,6 @@ pub const Value = extern union { |
| 864 | return compare(a, .eq, b); | 949 | return compare(a, .eq, b); |
| 865 | } | 950 | } |
| 866 | | 951 | |
| 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 | | | |
| 875 | /// Asserts the value is a pointer and dereferences it. | 952 | /// Asserts the value is a pointer and dereferences it. |
| 876 | /// Returns error.AnalysisFail if the pointer points to a Decl that failed semantic analysis. | 953 | /// Returns error.AnalysisFail if the pointer points to a Decl that failed semantic analysis. |
| 877 | pub fn pointerDeref(self: Value, allocator: *Allocator) error{ AnalysisFail, OutOfMemory }!Value { | 954 | pub fn pointerDeref(self: Value, allocator: *Allocator) error{ AnalysisFail, OutOfMemory }!Value { |
| ... | @@ -928,6 +1005,11 @@ pub const Value = extern union { | ... | @@ -928,6 +1005,11 @@ pub const Value = extern union { |
| 928 | .bytes, | 1005 | .bytes, |
| 929 | .undef, | 1006 | .undef, |
| 930 | .repeated, | 1007 | .repeated, |
| | 1008 | .float, |
| | 1009 | .float_16, |
| | 1010 | .float_32, |
| | 1011 | .float_64, |
| | 1012 | .float_128, |
| 931 | => unreachable, | 1013 | => unreachable, |
| 932 | | 1014 | |
| 933 | .the_one_possible_value => Value.initTag(.the_one_possible_value), | 1015 | .the_one_possible_value => Value.initTag(.the_one_possible_value), |
| ... | @@ -999,6 +1081,11 @@ pub const Value = extern union { | ... | @@ -999,6 +1081,11 @@ pub const Value = extern union { |
| 999 | .elem_ptr, | 1081 | .elem_ptr, |
| 1000 | .ref_val, | 1082 | .ref_val, |
| 1001 | .decl_ref, | 1083 | .decl_ref, |
| | 1084 | .float, |
| | 1085 | .float_16, |
| | 1086 | .float_32, |
| | 1087 | .float_64, |
| | 1088 | .float_128, |
| 1002 | => unreachable, | 1089 | => unreachable, |
| 1003 | | 1090 | |
| 1004 | .bytes => { | 1091 | .bytes => { |
| ... | @@ -1085,6 +1172,11 @@ pub const Value = extern union { | ... | @@ -1085,6 +1172,11 @@ pub const Value = extern union { |
| 1085 | .elem_ptr, | 1172 | .elem_ptr, |
| 1086 | .bytes, | 1173 | .bytes, |
| 1087 | .repeated, | 1174 | .repeated, |
| | 1175 | .float, |
| | 1176 | .float_16, |
| | 1177 | .float_32, |
| | 1178 | .float_64, |
| | 1179 | .float_128, |
| 1088 | => false, | 1180 | => false, |
| 1089 | | 1181 | |
| 1090 | .undef => unreachable, | 1182 | .undef => unreachable, |
| ... | @@ -1092,6 +1184,21 @@ pub const Value = extern union { | ... | @@ -1092,6 +1184,21 @@ pub const Value = extern union { |
| 1092 | }; | 1184 | }; |
| 1093 | } | 1185 | } |
| 1094 | | 1186 | |
| | 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 | |
| 1095 | /// This type is not copyable since it may contain pointers to its inner data. | 1202 | /// This type is not copyable since it may contain pointers to its inner data. |
| 1096 | pub const Payload = struct { | 1203 | pub const Payload = struct { |
| 1097 | tag: Tag, | 1204 | tag: Tag, |
| ... | @@ -1168,6 +1275,26 @@ pub const Value = extern union { | ... | @@ -1168,6 +1275,26 @@ pub const Value = extern union { |
| 1168 | /// is stored externally. | 1275 | /// is stored externally. |
| 1169 | val: Value, | 1276 | val: Value, |
| 1170 | }; | 1277 | }; |
| | 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 | }; |
| 1171 | }; | 1298 | }; |
| 1172 | | 1299 | |
| 1173 | /// Big enough to fit any non-BigInt value | 1300 | /// Big enough to fit any non-BigInt value |