| ... | ... | @@ -11,6 +11,7 @@ |
| 11 | 11 | |
| 12 | 12 | #include <stdarg.h> |
| 13 | 13 | #include <stdio.h> |
| 14 | #include <limits.h> |
| 14 | 15 | |
| 15 | 16 | |
| 16 | 17 | static const char *bin_op_str(BinOpType bin_op) { |
| ... | ... | @@ -278,9 +279,7 @@ void ast_print(AstNode *node, int indent) { |
| 278 | 279 | NumLit num_lit = node->data.number_literal.kind; |
| 279 | 280 | const char *name = node_type_str(node->type); |
| 280 | 281 | const char *kind_str = num_lit_str(num_lit); |
| 281 | | if (is_num_lit_signed(num_lit)) { |
| 282 | | fprintf(stderr, "%s %s %" PRId64 "\n", name, kind_str, node->data.number_literal.data.x_int); |
| 283 | | } else if (is_num_lit_unsigned(num_lit)) { |
| 282 | if (is_num_lit_unsigned(num_lit)) { |
| 284 | 283 | fprintf(stderr, "%s %s %" PRIu64 "\n", name, kind_str, node->data.number_literal.data.x_uint); |
| 285 | 284 | } else { |
| 286 | 285 | fprintf(stderr, "%s %s %f\n", name, kind_str, node->data.number_literal.data.x_float); |
| ... | ... | @@ -585,187 +584,152 @@ static void parse_string_literal(ParseContext *pc, Token *token, Buf *buf, bool |
| 585 | 584 | if (offset_map) offset_map->append(pos); |
| 586 | 585 | } |
| 587 | 586 | |
| 588 | | enum ParseNumLitState { |
| 589 | | ParseNumLitStateStart, |
| 590 | | ParseNumLitStateBase, |
| 591 | | ParseNumLitStateDigits, |
| 592 | | ParseNumLitStateExpectFirstDigit, |
| 593 | | ParseNumLitStateDecimal, |
| 594 | | ParseNumLitStateESign, |
| 595 | | ParseNumLitStateEDigit, |
| 596 | | }; |
| 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) { |
| 589 | unsigned long long x = initial_value; |
| 597 | 590 | |
| 598 | | static void parse_number_literal(ParseContext *pc, Token *token, AstNodeNumberLiteral *num_lit) { |
| 599 | | ParseNumLitState state = ParseNumLitStateStart; |
| 600 | | unsigned long long base = 10; |
| 601 | | bool negative = false; |
| 602 | | int digits_start; |
| 603 | | int digits_end; |
| 604 | | int decimal_start = -1; |
| 605 | | int decimal_end; |
| 606 | | bool e_present = false; |
| 607 | | bool e_positive; |
| 608 | | int e_digit_start; |
| 609 | | int e_digit_end; |
| 610 | | |
| 611 | | for (int i = token->start_pos; i < token->end_pos; i += 1) { |
| 591 | for (int i = digits_start; i < digits_end; i++) { |
| 612 | 592 | uint8_t c = *((uint8_t*)buf_ptr(pc->buf) + i); |
| 613 | | switch (state) { |
| 614 | | case ParseNumLitStateStart: |
| 615 | | if (c == '-') { |
| 616 | | negative = true; |
| 617 | | } else if (c == '0') { |
| 618 | | state = ParseNumLitStateBase; |
| 619 | | } else if (c >= '1' && c <= '9') { |
| 620 | | digits_start = i; |
| 621 | | state = ParseNumLitStateDigits; |
| 622 | | } else { |
| 623 | | zig_unreachable(); |
| 624 | | } |
| 625 | | break; |
| 626 | | case ParseNumLitStateBase: |
| 627 | | if (c == 'x') { |
| 628 | | base = 16; |
| 629 | | state = ParseNumLitStateExpectFirstDigit; |
| 630 | | } else if (c == 'o') { |
| 631 | | base = 8; |
| 632 | | state = ParseNumLitStateExpectFirstDigit; |
| 633 | | } else if (c == 'b') { |
| 634 | | base = 2; |
| 635 | | state = ParseNumLitStateExpectFirstDigit; |
| 636 | | } else { |
| 637 | | zig_unreachable(); |
| 638 | | } |
| 639 | | break; |
| 593 | unsigned long long digit = get_digit_value(c); |
| 640 | 594 | |
| 641 | | case ParseNumLitStateExpectFirstDigit: |
| 642 | | state = ParseNumLitStateDigits; |
| 643 | | break; |
| 595 | // x *= radix; |
| 596 | if (__builtin_umulll_overflow(x, radix, &x)) { |
| 597 | *overflow = true; |
| 598 | return 0; |
| 599 | } |
| 644 | 600 | |
| 645 | | case ParseNumLitStateDigits: |
| 646 | | if (c == '.') { |
| 647 | | assert(base == 10); |
| 648 | | digits_end = i; |
| 649 | | decimal_start = i + 1; |
| 650 | | state = ParseNumLitStateDecimal; |
| 651 | | } |
| 652 | | break; |
| 653 | | case ParseNumLitStateDecimal: |
| 654 | | if (c == 'E') { |
| 655 | | e_present = false; |
| 656 | | decimal_end = i; |
| 657 | | state = ParseNumLitStateESign; |
| 658 | | } |
| 659 | | break; |
| 660 | | case ParseNumLitStateESign: |
| 661 | | if (c == '+') { |
| 662 | | e_positive = true; |
| 663 | | e_digit_start = i + 1; |
| 664 | | state = ParseNumLitStateEDigit; |
| 665 | | } else if (c == '-') { |
| 666 | | e_positive = false; |
| 667 | | e_digit_start = i + 1; |
| 668 | | state = ParseNumLitStateEDigit; |
| 669 | | } else { |
| 670 | | zig_unreachable(); |
| 671 | | } |
| 672 | | break; |
| 673 | | case ParseNumLitStateEDigit: |
| 674 | | assert(c >= '0' && c <= '9'); |
| 675 | | break; |
| 601 | // x += digit |
| 602 | if (__builtin_uaddll_overflow(x, digit, &x)) { |
| 603 | *overflow = true; |
| 604 | return 0; |
| 676 | 605 | } |
| 677 | 606 | } |
| 607 | return x; |
| 608 | } |
| 678 | 609 | |
| 679 | | switch (state) { |
| 680 | | case ParseNumLitStateDigits: |
| 681 | | digits_end = token->end_pos; |
| 682 | | break; |
| 683 | | case ParseNumLitStateDecimal: |
| 684 | | decimal_end = token->end_pos; |
| 685 | | break; |
| 686 | | case ParseNumLitStateEDigit: |
| 687 | | e_digit_end = token->end_pos; |
| 688 | | break; |
| 689 | | case ParseNumLitStateBase: |
| 690 | | num_lit->kind = NumLitU8; |
| 691 | | num_lit->data.x_uint = 0; |
| 692 | | return; |
| 693 | | case ParseNumLitStateESign: |
| 694 | | case ParseNumLitStateExpectFirstDigit: |
| 695 | | case ParseNumLitStateStart: |
| 696 | | zig_unreachable(); |
| 610 | static void parse_number_literal(ParseContext *pc, Token *token, AstNodeNumberLiteral *num_lit) { |
| 611 | assert(token->id == TokenIdNumberLiteral); |
| 612 | |
| 613 | int whole_number_start = token->start_pos; |
| 614 | if (token->radix != 10) { |
| 615 | // skip the "0x" |
| 616 | whole_number_start += 2; |
| 697 | 617 | } |
| 698 | 618 | |
| 699 | | if (decimal_start >= 0) { |
| 700 | | // float |
| 701 | | double x; |
| 702 | | |
| 703 | | (void)x; |
| 704 | | (void)decimal_end; |
| 705 | | (void)e_present; |
| 706 | | (void)e_positive; |
| 707 | | (void)e_digit_start; |
| 708 | | (void)e_digit_end; |
| 709 | | zig_panic("TODO parse float"); |
| 710 | | } else { |
| 619 | int whole_number_end = token->decimal_point_pos; |
| 620 | if (whole_number_end <= whole_number_start) { |
| 621 | // TODO: error for empty whole number part |
| 622 | return; |
| 623 | } |
| 624 | |
| 625 | if (token->decimal_point_pos == token->end_pos) { |
| 711 | 626 | // integer |
| 712 | | unsigned long long x = 0; |
| 627 | unsigned long long whole_number = parse_int_digits(pc, whole_number_start, whole_number_end, |
| 628 | token->radix, 0, &num_lit->overflow); |
| 629 | if (num_lit->overflow) return; |
| 713 | 630 | |
| 714 | | unsigned long long mult = 1; |
| 715 | | for (int i = digits_end - 1; ; i -= 1) { |
| 716 | | uint8_t c = *((uint8_t*)buf_ptr(pc->buf) + i); |
| 717 | | unsigned long long digit = (c - '0'); |
| 631 | num_lit->data.x_uint = whole_number; |
| 718 | 632 | |
| 719 | | // digit *= mult |
| 720 | | if (__builtin_umulll_overflow(digit, mult, &digit)) { |
| 721 | | num_lit->overflow = true; |
| 633 | if (whole_number <= UINT8_MAX) { |
| 634 | num_lit->kind = NumLitU8; |
| 635 | } else if (whole_number <= UINT16_MAX) { |
| 636 | num_lit->kind = NumLitU16; |
| 637 | } else if (whole_number <= UINT32_MAX) { |
| 638 | num_lit->kind = NumLitU32; |
| 639 | } else { |
| 640 | num_lit->kind = NumLitU64; |
| 641 | } |
| 642 | } else { |
| 643 | // 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) { |
| 651 | // fraction |
| 652 | int fraction_start = token->decimal_point_pos + 1; |
| 653 | int fraction_end = token->exponent_marker_pos; |
| 654 | if (fraction_end <= fraction_start) { |
| 655 | // TODO: error for empty fraction part |
| 722 | 656 | return; |
| 723 | 657 | } |
| 724 | 658 | |
| 725 | | // x += digit |
| 726 | | if (__builtin_uaddll_overflow(x, digit, &x)) { |
| 727 | | num_lit->overflow = true; |
| 659 | // TODO: check for where the fraction got too precise instead of just saying overflow |
| 660 | significand_as_int = parse_int_digits(pc, fraction_start, fraction_end, |
| 661 | token->radix, significand_as_int, &num_lit->overflow); |
| 662 | if (num_lit->overflow) return; |
| 663 | |
| 664 | // adjust the exponent to compensate for us effectively moving |
| 665 | // the decimal point all the way to the right |
| 666 | exponent = -(fraction_end - fraction_start); |
| 667 | } |
| 668 | |
| 669 | if (token->exponent_marker_pos < token->end_pos) { |
| 670 | // exponent |
| 671 | int exponent_start = token->exponent_marker_pos + 1; |
| 672 | int exponent_end = token->end_pos; |
| 673 | if (exponent_end <= exponent_start) { |
| 674 | // TODO: error for empty exponent part |
| 728 | 675 | return; |
| 729 | 676 | } |
| 730 | 677 | |
| 731 | | if (i == digits_start) |
| 732 | | break; |
| 678 | bool is_exponent_negative = false; |
| 679 | uint8_t c = *((uint8_t*)buf_ptr(pc->buf) + exponent_start); |
| 680 | if (c == '+') { |
| 681 | exponent_start += 1; |
| 682 | } else if (c == '-') { |
| 683 | exponent_start += 1; |
| 684 | is_exponent_negative = true; |
| 685 | } |
| 733 | 686 | |
| 734 | | // mult *= base |
| 735 | | if (__builtin_umulll_overflow(mult, base, &mult)) { |
| 687 | if (exponent_end <= exponent_start) { |
| 688 | // TODO: error for empty exponent part |
| 689 | return; |
| 690 | } |
| 691 | |
| 692 | unsigned long long specified_exponent = parse_int_digits(pc, exponent_start, exponent_end, |
| 693 | 10, 0, &num_lit->overflow); |
| 694 | // TODO: this check is a little silly |
| 695 | if (specified_exponent >= LONG_LONG_MAX) { |
| 736 | 696 | num_lit->overflow = true; |
| 737 | 697 | return; |
| 738 | 698 | } |
| 699 | if (is_exponent_negative) { |
| 700 | exponent -= specified_exponent; |
| 701 | } else { |
| 702 | exponent += specified_exponent; |
| 703 | } |
| 739 | 704 | } |
| 740 | 705 | |
| 741 | | if (negative) { |
| 742 | | if (x <= 128ull) { |
| 743 | | num_lit->kind = NumLitI8; |
| 744 | | } else if (x <= 32768ull) { |
| 745 | | num_lit->kind = NumLitI16; |
| 746 | | } else if (x <= 2147483648ull) { |
| 747 | | num_lit->kind = NumLitI32; |
| 748 | | } else if (x <= 9223372036854775808ull) { |
| 749 | | num_lit->kind = NumLitI64; |
| 750 | | } else { |
| 706 | uint64_t significand_bits; |
| 707 | uint64_t exponent_bits; |
| 708 | if (significand_as_int != 0) { |
| 709 | // normalize the significand |
| 710 | int significand_magnitude = __builtin_clzll(1) - __builtin_clzll(significand_as_int); |
| 711 | exponent += significand_magnitude; |
| 712 | if (!(-1023 <= exponent && exponent < 1023)) { |
| 751 | 713 | num_lit->overflow = true; |
| 752 | 714 | return; |
| 753 | 715 | } |
| 754 | 716 | |
| 755 | | num_lit->data.x_int = -((int64_t)x); |
| 717 | // this should chop off exactly one 1 bit from the top. |
| 718 | significand_bits = ((uint64_t)significand_as_int << (52 - significand_magnitude)) & 0xfffffffffffffULL; |
| 719 | exponent_bits = exponent + 1023; |
| 756 | 720 | } else { |
| 757 | | num_lit->data.x_uint = x; |
| 758 | | |
| 759 | | if (x <= UINT8_MAX) { |
| 760 | | num_lit->kind = NumLitU8; |
| 761 | | } else if (x <= UINT16_MAX) { |
| 762 | | num_lit->kind = NumLitU16; |
| 763 | | } else if (x <= UINT32_MAX) { |
| 764 | | num_lit->kind = NumLitU32; |
| 765 | | } else { |
| 766 | | num_lit->kind = NumLitU64; |
| 767 | | } |
| 721 | // 0 is all 0's |
| 722 | significand_bits = 0; |
| 723 | exponent_bits = 0; |
| 768 | 724 | } |
| 725 | |
| 726 | uint64_t double_bits = (exponent_bits << 52) | significand_bits; |
| 727 | // TODO: check and swap endian |
| 728 | double x = *(double *)&double_bits; |
| 729 | |
| 730 | num_lit->data.x_float = x; |
| 731 | // TODO: see if we can store it in f32 |
| 732 | num_lit->kind = NumLitF64; |
| 769 | 733 | } |
| 770 | 734 | } |
| 771 | 735 | |
| ... | ... | @@ -2366,14 +2330,6 @@ const char *num_lit_str(NumLit num_lit) { |
| 2366 | 2330 | return "f64"; |
| 2367 | 2331 | case NumLitF128: |
| 2368 | 2332 | return "f128"; |
| 2369 | | case NumLitI8: |
| 2370 | | return "i8"; |
| 2371 | | case NumLitI16: |
| 2372 | | return "i16"; |
| 2373 | | case NumLitI32: |
| 2374 | | return "i32"; |
| 2375 | | case NumLitI64: |
| 2376 | | return "i64"; |
| 2377 | 2333 | case NumLitU8: |
| 2378 | 2334 | return "u8"; |
| 2379 | 2335 | case NumLitU16: |
| ... | ... | @@ -2388,37 +2344,11 @@ const char *num_lit_str(NumLit num_lit) { |
| 2388 | 2344 | zig_unreachable(); |
| 2389 | 2345 | } |
| 2390 | 2346 | |
| 2391 | | bool is_num_lit_signed(NumLit num_lit) { |
| 2392 | | switch (num_lit) { |
| 2393 | | case NumLitI8: |
| 2394 | | case NumLitI16: |
| 2395 | | case NumLitI32: |
| 2396 | | case NumLitI64: |
| 2397 | | return true; |
| 2398 | | |
| 2399 | | case NumLitF32: |
| 2400 | | case NumLitF64: |
| 2401 | | case NumLitF128: |
| 2402 | | case NumLitU8: |
| 2403 | | case NumLitU16: |
| 2404 | | case NumLitU32: |
| 2405 | | case NumLitU64: |
| 2406 | | return false; |
| 2407 | | case NumLitCount: |
| 2408 | | zig_unreachable(); |
| 2409 | | } |
| 2410 | | zig_unreachable(); |
| 2411 | | } |
| 2412 | | |
| 2413 | 2347 | bool is_num_lit_unsigned(NumLit num_lit) { |
| 2414 | 2348 | switch (num_lit) { |
| 2415 | 2349 | case NumLitF32: |
| 2416 | 2350 | case NumLitF64: |
| 2417 | 2351 | case NumLitF128: |
| 2418 | | case NumLitI8: |
| 2419 | | case NumLitI16: |
| 2420 | | case NumLitI32: |
| 2421 | | case NumLitI64: |
| 2422 | 2352 | return false; |
| 2423 | 2353 | case NumLitU8: |
| 2424 | 2354 | case NumLitU16: |
| ... | ... | @@ -2437,10 +2367,6 @@ bool is_num_lit_float(NumLit num_lit) { |
| 2437 | 2367 | case NumLitF64: |
| 2438 | 2368 | case NumLitF128: |
| 2439 | 2369 | return true; |
| 2440 | | case NumLitI8: |
| 2441 | | case NumLitI16: |
| 2442 | | case NumLitI32: |
| 2443 | | case NumLitI64: |
| 2444 | 2370 | case NumLitU8: |
| 2445 | 2371 | case NumLitU16: |
| 2446 | 2372 | case NumLitU32: |
| ... | ... | @@ -2454,17 +2380,13 @@ bool is_num_lit_float(NumLit num_lit) { |
| 2454 | 2380 | |
| 2455 | 2381 | uint64_t num_lit_bit_count(NumLit num_lit) { |
| 2456 | 2382 | switch (num_lit) { |
| 2457 | | case NumLitI8: |
| 2458 | 2383 | case NumLitU8: |
| 2459 | 2384 | return 8; |
| 2460 | | case NumLitI16: |
| 2461 | 2385 | case NumLitU16: |
| 2462 | 2386 | return 16; |
| 2463 | | case NumLitI32: |
| 2464 | 2387 | case NumLitU32: |
| 2465 | 2388 | case NumLitF32: |
| 2466 | 2389 | return 32; |
| 2467 | | case NumLitI64: |
| 2468 | 2390 | case NumLitU64: |
| 2469 | 2391 | case NumLitF64: |
| 2470 | 2392 | return 64; |