| ... | @@ -585,10 +585,13 @@ static void parse_string_literal(ParseContext *pc, Token *token, Buf *buf, bool | ... | @@ -585,10 +585,13 @@ static void parse_string_literal(ParseContext *pc, Token *token, Buf *buf, bool |
| 585 | } | 585 | } |
| 586 | | 586 | |
| 587 | static unsigned long long parse_int_digits(ParseContext *pc, int digits_start, int digits_end, int radix, | 587 | static unsigned long long parse_int_digits(ParseContext *pc, int digits_start, int digits_end, int radix, |
| 588 | unsigned long long initial_value, bool *overflow) { | 588 | int skip_index, bool *overflow) |
| 589 | unsigned long long x = initial_value; | 589 | { |
| | 590 | unsigned long long x = 0; |
| 590 | | 591 | |
| 591 | for (int i = digits_start; i < digits_end; i++) { | 592 | for (int i = digits_start; i < digits_end; i++) { |
| | 593 | if (i == skip_index) |
| | 594 | continue; |
| 592 | uint8_t c = *((uint8_t*)buf_ptr(pc->buf) + i); | 595 | uint8_t c = *((uint8_t*)buf_ptr(pc->buf) + i); |
| 593 | unsigned long long digit = get_digit_value(c); | 596 | unsigned long long digit = get_digit_value(c); |
| 594 | | 597 | |
| ... | @@ -625,7 +628,7 @@ static void parse_number_literal(ParseContext *pc, Token *token, AstNodeNumberLi | ... | @@ -625,7 +628,7 @@ static void parse_number_literal(ParseContext *pc, Token *token, AstNodeNumberLi |
| 625 | if (token->decimal_point_pos == token->end_pos) { | 628 | if (token->decimal_point_pos == token->end_pos) { |
| 626 | // integer | 629 | // integer |
| 627 | unsigned long long whole_number = parse_int_digits(pc, whole_number_start, whole_number_end, | 630 | unsigned long long whole_number = parse_int_digits(pc, whole_number_start, whole_number_end, |
| 628 | token->radix, 0, &num_lit->overflow); | 631 | token->radix, -1, &num_lit->overflow); |
| 629 | if (num_lit->overflow) return; | 632 | if (num_lit->overflow) return; |
| 630 | | 633 | |
| 631 | num_lit->data.x_uint = whole_number; | 634 | num_lit->data.x_uint = whole_number; |
| ... | @@ -641,12 +644,6 @@ static void parse_number_literal(ParseContext *pc, Token *token, AstNodeNumberLi | ... | @@ -641,12 +644,6 @@ static void parse_number_literal(ParseContext *pc, Token *token, AstNodeNumberLi |
| 641 | } | 644 | } |
| 642 | } else { | 645 | } else { |
| 643 | // float | 646 | // float |
| 644 | // TODO: trim leading and trailing zeros in the significand digit sequence | | |
| 645 | unsigned long long significand_as_int = parse_int_digits(pc, whole_number_start, whole_number_end, | | |
| 646 | token->radix, 0, &num_lit->overflow); | | |
| 647 | if (num_lit->overflow) return; | | |
| 648 | | | |
| 649 | int exponent = 0; | | |
| 650 | if (token->decimal_point_pos < token->exponent_marker_pos) { | 647 | if (token->decimal_point_pos < token->exponent_marker_pos) { |
| 651 | // fraction | 648 | // fraction |
| 652 | int fraction_start = token->decimal_point_pos + 1; | 649 | int fraction_start = token->decimal_point_pos + 1; |
| ... | @@ -655,15 +652,44 @@ static void parse_number_literal(ParseContext *pc, Token *token, AstNodeNumberLi | ... | @@ -655,15 +652,44 @@ static void parse_number_literal(ParseContext *pc, Token *token, AstNodeNumberLi |
| 655 | // TODO: error for empty fraction part | 652 | // TODO: error for empty fraction part |
| 656 | return; | 653 | return; |
| 657 | } | 654 | } |
| | 655 | } |
| 658 | | 656 | |
| 659 | // TODO: check for where the fraction got too precise instead of just saying overflow | 657 | // trim leading and trailing zeros in the significand digit sequence |
| 660 | significand_as_int = parse_int_digits(pc, fraction_start, fraction_end, | 658 | int significand_start = whole_number_start; |
| 661 | token->radix, significand_as_int, &num_lit->overflow); | 659 | for (; significand_start < token->exponent_marker_pos; significand_start++) { |
| 662 | if (num_lit->overflow) return; | 660 | if (significand_start == token->decimal_point_pos) |
| | 661 | continue; |
| | 662 | uint8_t c = *((uint8_t*)buf_ptr(pc->buf) + significand_start); |
| | 663 | if (c != '0') |
| | 664 | break; |
| | 665 | } |
| | 666 | int significand_end = token->exponent_marker_pos; |
| | 667 | for (; significand_end - 1 > significand_start; significand_end--) { |
| | 668 | if (significand_end - 1 <= token->decimal_point_pos) { |
| | 669 | significand_end = token->decimal_point_pos; |
| | 670 | break; |
| | 671 | } |
| | 672 | uint8_t c = *((uint8_t*)buf_ptr(pc->buf) + significand_end - 1); |
| | 673 | if (c != '0') |
| | 674 | break; |
| | 675 | } |
| 663 | | 676 | |
| 664 | // adjust the exponent to compensate for us effectively moving | 677 | unsigned long long significand_as_int = parse_int_digits(pc, significand_start, significand_end, |
| 665 | // the decimal point all the way to the right | 678 | token->radix, token->decimal_point_pos, &num_lit->overflow); |
| 666 | exponent = -(fraction_end - fraction_start); | 679 | if (num_lit->overflow) return; |
| | 680 | |
| | 681 | int exponent_in_bin_or_dec = 0; |
| | 682 | if (significand_end > token->decimal_point_pos) { |
| | 683 | exponent_in_bin_or_dec = token->decimal_point_pos + 1 - significand_end; |
| | 684 | if (token->radix == 2) { |
| | 685 | // already good |
| | 686 | } else if (token->radix == 8) { |
| | 687 | exponent_in_bin_or_dec *= 3; |
| | 688 | } else if (token->radix == 10) { |
| | 689 | // already good |
| | 690 | } else if (token->radix == 16) { |
| | 691 | exponent_in_bin_or_dec *= 4; |
| | 692 | } else zig_unreachable(); |
| 667 | } | 693 | } |
| 668 | | 694 | |
| 669 | if (token->exponent_marker_pos < token->end_pos) { | 695 | if (token->exponent_marker_pos < token->end_pos) { |
| ... | @@ -674,7 +700,6 @@ static void parse_number_literal(ParseContext *pc, Token *token, AstNodeNumberLi | ... | @@ -674,7 +700,6 @@ static void parse_number_literal(ParseContext *pc, Token *token, AstNodeNumberLi |
| 674 | // TODO: error for empty exponent part | 700 | // TODO: error for empty exponent part |
| 675 | return; | 701 | return; |
| 676 | } | 702 | } |
| 677 | | | |
| 678 | bool is_exponent_negative = false; | 703 | bool is_exponent_negative = false; |
| 679 | uint8_t c = *((uint8_t*)buf_ptr(pc->buf) + exponent_start); | 704 | uint8_t c = *((uint8_t*)buf_ptr(pc->buf) + exponent_start); |
| 680 | if (c == '+') { | 705 | if (c == '+') { |
| ... | @@ -690,16 +715,17 @@ static void parse_number_literal(ParseContext *pc, Token *token, AstNodeNumberLi | ... | @@ -690,16 +715,17 @@ static void parse_number_literal(ParseContext *pc, Token *token, AstNodeNumberLi |
| 690 | } | 715 | } |
| 691 | | 716 | |
| 692 | unsigned long long specified_exponent = parse_int_digits(pc, exponent_start, exponent_end, | 717 | unsigned long long specified_exponent = parse_int_digits(pc, exponent_start, exponent_end, |
| 693 | 10, 0, &num_lit->overflow); | 718 | 10, -1, &num_lit->overflow); |
| 694 | // TODO: this check is a little silly | 719 | // TODO: this check is a little silly |
| 695 | if (specified_exponent >= LONG_LONG_MAX) { | 720 | if (specified_exponent >= LONG_LONG_MAX) { |
| 696 | num_lit->overflow = true; | 721 | num_lit->overflow = true; |
| 697 | return; | 722 | return; |
| 698 | } | 723 | } |
| | 724 | |
| 699 | if (is_exponent_negative) { | 725 | if (is_exponent_negative) { |
| 700 | exponent -= specified_exponent; | 726 | exponent_in_bin_or_dec -= specified_exponent; |
| 701 | } else { | 727 | } else { |
| 702 | exponent += specified_exponent; | 728 | exponent_in_bin_or_dec += specified_exponent; |
| 703 | } | 729 | } |
| 704 | } | 730 | } |
| 705 | | 731 | |
| ... | @@ -707,16 +733,20 @@ static void parse_number_literal(ParseContext *pc, Token *token, AstNodeNumberLi | ... | @@ -707,16 +733,20 @@ static void parse_number_literal(ParseContext *pc, Token *token, AstNodeNumberLi |
| 707 | uint64_t exponent_bits; | 733 | uint64_t exponent_bits; |
| 708 | if (significand_as_int != 0) { | 734 | if (significand_as_int != 0) { |
| 709 | // normalize the significand | 735 | // normalize the significand |
| 710 | int significand_magnitude = __builtin_clzll(1) - __builtin_clzll(significand_as_int); | 736 | if (token->radix == 10) { |
| 711 | exponent += significand_magnitude; | 737 | zig_panic("TODO: decimal floats"); |
| 712 | if (!(-1023 <= exponent && exponent < 1023)) { | 738 | } else { |
| 713 | num_lit->overflow = true; | 739 | int significand_magnitude_in_bin = __builtin_clzll(1) - __builtin_clzll(significand_as_int); |
| 714 | return; | 740 | exponent_in_bin_or_dec += significand_magnitude_in_bin; |
| 715 | } | 741 | if (!(-1023 <= exponent_in_bin_or_dec && exponent_in_bin_or_dec < 1023)) { |
| | 742 | num_lit->overflow = true; |
| | 743 | return; |
| | 744 | } |
| 716 | | 745 | |
| 717 | // this should chop off exactly one 1 bit from the top. | 746 | // this should chop off exactly one 1 bit from the top. |
| 718 | significand_bits = ((uint64_t)significand_as_int << (52 - significand_magnitude)) & 0xfffffffffffffULL; | 747 | significand_bits = ((uint64_t)significand_as_int << (52 - significand_magnitude_in_bin)) & 0xfffffffffffffULL; |
| 719 | exponent_bits = exponent + 1023; | 748 | exponent_bits = exponent_in_bin_or_dec + 1023; |
| | 749 | } |
| 720 | } else { | 750 | } else { |
| 721 | // 0 is all 0's | 751 | // 0 is all 0's |
| 722 | significand_bits = 0; | 752 | significand_bits = 0; |