| ... | ... | @@ -80,6 +80,11 @@ pub const Value = extern union { |
| 80 | 80 | elem_ptr, |
| 81 | 81 | bytes, |
| 82 | 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 | 89 | pub const last_no_payload_tag = Tag.bool_false; |
| 85 | 90 | pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1; |
| ... | ... | @@ -213,6 +218,10 @@ pub const Value = extern union { |
| 213 | 218 | }; |
| 214 | 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 | 309 | try out_stream.writeAll("(repeated) "); |
| 301 | 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 | 393 | .elem_ptr, |
| 381 | 394 | .bytes, |
| 382 | 395 | .repeated, |
| 396 | .float, |
| 397 | .float_16, |
| 398 | .float_32, |
| 399 | .float_64, |
| 400 | .float_128, |
| 383 | 401 | => unreachable, |
| 384 | 402 | }; |
| 385 | 403 | } |
| ... | ... | @@ -435,6 +453,11 @@ pub const Value = extern union { |
| 435 | 453 | .bytes, |
| 436 | 454 | .undef, |
| 437 | 455 | .repeated, |
| 456 | .float, |
| 457 | .float_16, |
| 458 | .float_32, |
| 459 | .float_64, |
| 460 | .float_128, |
| 438 | 461 | => unreachable, |
| 439 | 462 | |
| 440 | 463 | .the_one_possible_value, // An integer with one possible value is always zero. |
| ... | ... | @@ -502,6 +525,11 @@ pub const Value = extern union { |
| 502 | 525 | .bytes, |
| 503 | 526 | .undef, |
| 504 | 527 | .repeated, |
| 528 | .float, |
| 529 | .float_16, |
| 530 | .float_32, |
| 531 | .float_64, |
| 532 | .float_128, |
| 505 | 533 | => unreachable, |
| 506 | 534 | |
| 507 | 535 | .zero, |
| ... | ... | @@ -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 | 568 | /// Asserts the value is an integer and not undefined. |
| 522 | 569 | /// Returns the number of bits the value requires to represent stored in twos complement form. |
| 523 | 570 | pub fn intBitCountTwosComp(self: Value) usize { |
| ... | ... | @@ -570,6 +617,11 @@ pub const Value = extern union { |
| 570 | 617 | .bytes, |
| 571 | 618 | .undef, |
| 572 | 619 | .repeated, |
| 620 | .float, |
| 621 | .float_16, |
| 622 | .float_32, |
| 623 | .float_64, |
| 624 | .float_128, |
| 573 | 625 | => unreachable, |
| 574 | 626 | |
| 575 | 627 | .the_one_possible_value, // an integer with one possible value is always zero |
| ... | ... | @@ -642,6 +694,11 @@ pub const Value = extern union { |
| 642 | 694 | .elem_ptr, |
| 643 | 695 | .bytes, |
| 644 | 696 | .repeated, |
| 697 | .float, |
| 698 | .float_16, |
| 699 | .float_32, |
| 700 | .float_64, |
| 701 | .float_128, |
| 645 | 702 | => unreachable, |
| 646 | 703 | |
| 647 | 704 | .zero, |
| ... | ... | @@ -762,11 +819,17 @@ pub const Value = extern union { |
| 762 | 819 | => unreachable, |
| 763 | 820 | |
| 764 | 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 | 831 | pub fn orderAgainstZero(lhs: Value) std.math.Order { |
| 769 | | switch (lhs.tag()) { |
| 832 | return switch (lhs.tag()) { |
| 770 | 833 | .ty, |
| 771 | 834 | .u8_type, |
| 772 | 835 | .i8_type, |
| ... | ... | @@ -820,15 +883,20 @@ pub const Value = extern union { |
| 820 | 883 | .zero, |
| 821 | 884 | .the_one_possible_value, // an integer with one possible value is always zero |
| 822 | 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), |
| 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 | }; |
| 832 | 900 | } |
| 833 | 901 | |
| 834 | 902 | /// Asserts the value is comparable. |
| ... | ... | @@ -840,7 +908,24 @@ pub const Value = extern union { |
| 840 | 908 | if (lhs_is_zero) return rhs.orderAgainstZero().invert(); |
| 841 | 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 | 930 | var lhs_bigint_space: BigIntSpace = undefined; |
| 846 | 931 | var rhs_bigint_space: BigIntSpace = undefined; |
| ... | ... | @@ -864,14 +949,6 @@ pub const Value = extern union { |
| 864 | 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 | 952 | /// Asserts the value is a pointer and dereferences it. |
| 876 | 953 | /// Returns error.AnalysisFail if the pointer points to a Decl that failed semantic analysis. |
| 877 | 954 | pub fn pointerDeref(self: Value, allocator: *Allocator) error{ AnalysisFail, OutOfMemory }!Value { |
| ... | ... | @@ -928,6 +1005,11 @@ pub const Value = extern union { |
| 928 | 1005 | .bytes, |
| 929 | 1006 | .undef, |
| 930 | 1007 | .repeated, |
| 1008 | .float, |
| 1009 | .float_16, |
| 1010 | .float_32, |
| 1011 | .float_64, |
| 1012 | .float_128, |
| 931 | 1013 | => unreachable, |
| 932 | 1014 | |
| 933 | 1015 | .the_one_possible_value => Value.initTag(.the_one_possible_value), |
| ... | ... | @@ -999,6 +1081,11 @@ pub const Value = extern union { |
| 999 | 1081 | .elem_ptr, |
| 1000 | 1082 | .ref_val, |
| 1001 | 1083 | .decl_ref, |
| 1084 | .float, |
| 1085 | .float_16, |
| 1086 | .float_32, |
| 1087 | .float_64, |
| 1088 | .float_128, |
| 1002 | 1089 | => unreachable, |
| 1003 | 1090 | |
| 1004 | 1091 | .bytes => { |
| ... | ... | @@ -1085,6 +1172,11 @@ pub const Value = extern union { |
| 1085 | 1172 | .elem_ptr, |
| 1086 | 1173 | .bytes, |
| 1087 | 1174 | .repeated, |
| 1175 | .float, |
| 1176 | .float_16, |
| 1177 | .float_32, |
| 1178 | .float_64, |
| 1179 | .float_128, |
| 1088 | 1180 | => false, |
| 1089 | 1181 | |
| 1090 | 1182 | .undef => unreachable, |
| ... | ... | @@ -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 | 1202 | /// This type is not copyable since it may contain pointers to its inner data. |
| 1096 | 1203 | pub const Payload = struct { |
| 1097 | 1204 | tag: Tag, |
| ... | ... | @@ -1168,6 +1275,26 @@ pub const Value = extern union { |
| 1168 | 1275 | /// is stored externally. |
| 1169 | 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 | 1300 | /// Big enough to fit any non-BigInt value |