| ... | @@ -11,6 +11,7 @@ | ... | @@ -11,6 +11,7 @@ |
| 11 | | 11 | |
| 12 | #include <stdarg.h> | 12 | #include <stdarg.h> |
| 13 | #include <stdio.h> | 13 | #include <stdio.h> |
| | 14 | #include <limits.h> |
| 14 | | 15 | |
| 15 | | 16 | |
| 16 | static const char *bin_op_str(BinOpType bin_op) { | 17 | static const char *bin_op_str(BinOpType bin_op) { |
| ... | @@ -278,9 +279,7 @@ void ast_print(AstNode *node, int indent) { | ... | @@ -278,9 +279,7 @@ void ast_print(AstNode *node, int indent) { |
| 278 | NumLit num_lit = node->data.number_literal.kind; | 279 | NumLit num_lit = node->data.number_literal.kind; |
| 279 | const char *name = node_type_str(node->type); | 280 | const char *name = node_type_str(node->type); |
| 280 | const char *kind_str = num_lit_str(num_lit); | 281 | const char *kind_str = num_lit_str(num_lit); |
| 281 | if (is_num_lit_signed(num_lit)) { | 282 | if (is_num_lit_unsigned(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)) { | | |
| 284 | fprintf(stderr, "%s %s %" PRIu64 "\n", name, kind_str, node->data.number_literal.data.x_uint); | 283 | fprintf(stderr, "%s %s %" PRIu64 "\n", name, kind_str, node->data.number_literal.data.x_uint); |
| 285 | } else { | 284 | } else { |
| 286 | fprintf(stderr, "%s %s %f\n", name, kind_str, node->data.number_literal.data.x_float); | 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,187 +584,152 @@ static void parse_string_literal(ParseContext *pc, Token *token, Buf *buf, bool |
| 585 | if (offset_map) offset_map->append(pos); | 584 | if (offset_map) offset_map->append(pos); |
| 586 | } | 585 | } |
| 587 | | 586 | |
| 588 | enum ParseNumLitState { | 587 | static unsigned long long parse_int_digits(ParseContext *pc, int digits_start, int digits_end, int radix, |
| 589 | ParseNumLitStateStart, | 588 | unsigned long long initial_value, bool *overflow) { |
| 590 | ParseNumLitStateBase, | 589 | unsigned long long x = initial_value; |
| 591 | ParseNumLitStateDigits, | | |
| 592 | ParseNumLitStateExpectFirstDigit, | | |
| 593 | ParseNumLitStateDecimal, | | |
| 594 | ParseNumLitStateESign, | | |
| 595 | ParseNumLitStateEDigit, | | |
| 596 | }; | | |
| 597 | | 590 | |
| 598 | static void parse_number_literal(ParseContext *pc, Token *token, AstNodeNumberLiteral *num_lit) { | 591 | for (int i = digits_start; i < digits_end; i++) { |
| 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) { | | |
| 612 | uint8_t c = *((uint8_t*)buf_ptr(pc->buf) + i); | 592 | uint8_t c = *((uint8_t*)buf_ptr(pc->buf) + i); |
| 613 | switch (state) { | 593 | unsigned long long digit = get_digit_value(c); |
| 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; | | |
| 640 | | 594 | |
| 641 | case ParseNumLitStateExpectFirstDigit: | 595 | // x *= radix; |
| 642 | state = ParseNumLitStateDigits; | 596 | if (__builtin_umulll_overflow(x, radix, &x)) { |
| 643 | break; | 597 | *overflow = true; |
| | 598 | return 0; |
| | 599 | } |
| 644 | | 600 | |
| 645 | case ParseNumLitStateDigits: | 601 | // x += digit |
| 646 | if (c == '.') { | 602 | if (__builtin_uaddll_overflow(x, digit, &x)) { |
| 647 | assert(base == 10); | 603 | *overflow = true; |
| 648 | digits_end = i; | 604 | return 0; |
| 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; | | |
| 676 | } | 605 | } |
| 677 | } | 606 | } |
| | 607 | return x; |
| | 608 | } |
| 678 | | 609 | |
| 679 | switch (state) { | 610 | static void parse_number_literal(ParseContext *pc, Token *token, AstNodeNumberLiteral *num_lit) { |
| 680 | case ParseNumLitStateDigits: | 611 | assert(token->id == TokenIdNumberLiteral); |
| 681 | digits_end = token->end_pos; | 612 | |
| 682 | break; | 613 | int whole_number_start = token->start_pos; |
| 683 | case ParseNumLitStateDecimal: | 614 | if (token->radix != 10) { |
| 684 | decimal_end = token->end_pos; | 615 | // skip the "0x" |
| 685 | break; | 616 | whole_number_start += 2; |
| 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(); | | |
| 697 | } | 617 | } |
| 698 | | 618 | |
| 699 | if (decimal_start >= 0) { | 619 | int whole_number_end = token->decimal_point_pos; |
| 700 | // float | 620 | if (whole_number_end <= whole_number_start) { |
| 701 | double x; | 621 | // TODO: error for empty whole number part |
| 702 | | 622 | return; |
| 703 | (void)x; | 623 | } |
| 704 | (void)decimal_end; | 624 | |
| 705 | (void)e_present; | 625 | if (token->decimal_point_pos == token->end_pos) { |
| 706 | (void)e_positive; | | |
| 707 | (void)e_digit_start; | | |
| 708 | (void)e_digit_end; | | |
| 709 | zig_panic("TODO parse float"); | | |
| 710 | } else { | | |
| 711 | // integer | 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; | 631 | num_lit->data.x_uint = whole_number; |
| 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'); | | |
| 718 | | 632 | |
| 719 | // digit *= mult | 633 | if (whole_number <= UINT8_MAX) { |
| 720 | if (__builtin_umulll_overflow(digit, mult, &digit)) { | 634 | num_lit->kind = NumLitU8; |
| 721 | num_lit->overflow = true; | 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 | return; | 656 | return; |
| 723 | } | 657 | } |
| 724 | | 658 | |
| 725 | // x += digit | 659 | // TODO: check for where the fraction got too precise instead of just saying overflow |
| 726 | if (__builtin_uaddll_overflow(x, digit, &x)) { | 660 | significand_as_int = parse_int_digits(pc, fraction_start, fraction_end, |
| 727 | num_lit->overflow = true; | 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 | return; | 675 | return; |
| 729 | } | 676 | } |
| 730 | | 677 | |
| 731 | if (i == digits_start) | 678 | bool is_exponent_negative = false; |
| 732 | break; | 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 | 687 | if (exponent_end <= exponent_start) { |
| 735 | if (__builtin_umulll_overflow(mult, base, &mult)) { | 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 | num_lit->overflow = true; | 696 | num_lit->overflow = true; |
| 737 | return; | 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) { | 706 | uint64_t significand_bits; |
| 742 | if (x <= 128ull) { | 707 | uint64_t exponent_bits; |
| 743 | num_lit->kind = NumLitI8; | 708 | if (significand_as_int != 0) { |
| 744 | } else if (x <= 32768ull) { | 709 | // normalize the significand |
| 745 | num_lit->kind = NumLitI16; | 710 | int significand_magnitude = __builtin_clzll(1) - __builtin_clzll(significand_as_int); |
| 746 | } else if (x <= 2147483648ull) { | 711 | exponent += significand_magnitude; |
| 747 | num_lit->kind = NumLitI32; | 712 | if (!(-1023 <= exponent && exponent < 1023)) { |
| 748 | } else if (x <= 9223372036854775808ull) { | | |
| 749 | num_lit->kind = NumLitI64; | | |
| 750 | } else { | | |
| 751 | num_lit->overflow = true; | 713 | num_lit->overflow = true; |
| 752 | return; | 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 | } else { | 720 | } else { |
| 757 | num_lit->data.x_uint = x; | 721 | // 0 is all 0's |
| 758 | | 722 | significand_bits = 0; |
| 759 | if (x <= UINT8_MAX) { | 723 | exponent_bits = 0; |
| 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 | } | | |
| 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,14 +2330,6 @@ const char *num_lit_str(NumLit num_lit) { |
| 2366 | return "f64"; | 2330 | return "f64"; |
| 2367 | case NumLitF128: | 2331 | case NumLitF128: |
| 2368 | return "f128"; | 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 | case NumLitU8: | 2333 | case NumLitU8: |
| 2378 | return "u8"; | 2334 | return "u8"; |
| 2379 | case NumLitU16: | 2335 | case NumLitU16: |
| ... | @@ -2388,37 +2344,11 @@ const char *num_lit_str(NumLit num_lit) { | ... | @@ -2388,37 +2344,11 @@ const char *num_lit_str(NumLit num_lit) { |
| 2388 | zig_unreachable(); | 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 | bool is_num_lit_unsigned(NumLit num_lit) { | 2347 | bool is_num_lit_unsigned(NumLit num_lit) { |
| 2414 | switch (num_lit) { | 2348 | switch (num_lit) { |
| 2415 | case NumLitF32: | 2349 | case NumLitF32: |
| 2416 | case NumLitF64: | 2350 | case NumLitF64: |
| 2417 | case NumLitF128: | 2351 | case NumLitF128: |
| 2418 | case NumLitI8: | | |
| 2419 | case NumLitI16: | | |
| 2420 | case NumLitI32: | | |
| 2421 | case NumLitI64: | | |
| 2422 | return false; | 2352 | return false; |
| 2423 | case NumLitU8: | 2353 | case NumLitU8: |
| 2424 | case NumLitU16: | 2354 | case NumLitU16: |
| ... | @@ -2437,10 +2367,6 @@ bool is_num_lit_float(NumLit num_lit) { | ... | @@ -2437,10 +2367,6 @@ bool is_num_lit_float(NumLit num_lit) { |
| 2437 | case NumLitF64: | 2367 | case NumLitF64: |
| 2438 | case NumLitF128: | 2368 | case NumLitF128: |
| 2439 | return true; | 2369 | return true; |
| 2440 | case NumLitI8: | | |
| 2441 | case NumLitI16: | | |
| 2442 | case NumLitI32: | | |
| 2443 | case NumLitI64: | | |
| 2444 | case NumLitU8: | 2370 | case NumLitU8: |
| 2445 | case NumLitU16: | 2371 | case NumLitU16: |
| 2446 | case NumLitU32: | 2372 | case NumLitU32: |
| ... | @@ -2454,17 +2380,13 @@ bool is_num_lit_float(NumLit num_lit) { | ... | @@ -2454,17 +2380,13 @@ bool is_num_lit_float(NumLit num_lit) { |
| 2454 | | 2380 | |
| 2455 | uint64_t num_lit_bit_count(NumLit num_lit) { | 2381 | uint64_t num_lit_bit_count(NumLit num_lit) { |
| 2456 | switch (num_lit) { | 2382 | switch (num_lit) { |
| 2457 | case NumLitI8: | | |
| 2458 | case NumLitU8: | 2383 | case NumLitU8: |
| 2459 | return 8; | 2384 | return 8; |
| 2460 | case NumLitI16: | | |
| 2461 | case NumLitU16: | 2385 | case NumLitU16: |
| 2462 | return 16; | 2386 | return 16; |
| 2463 | case NumLitI32: | | |
| 2464 | case NumLitU32: | 2387 | case NumLitU32: |
| 2465 | case NumLitF32: | 2388 | case NumLitF32: |
| 2466 | return 32; | 2389 | return 32; |
| 2467 | case NumLitI64: | | |
| 2468 | case NumLitU64: | 2390 | case NumLitU64: |
| 2469 | case NumLitF64: | 2391 | case NumLitF64: |
| 2470 | return 64; | 2392 | return 64; |