authorgravatar for thejoshwolfe@gmail.comJosh Wolfe <thejoshwolfe@gmail.com> 2015-12-15 04:05:43-07:00
committergravatar for thejoshwolfe@gmail.comJosh Wolfe <thejoshwolfe@gmail.com> 2015-12-15 04:05:53-07:00
logf2a9b40231f982b10c4d098c60b47da890396c1f
tree63a8b8af9120203ff6f7dfaa05681346276e3c94
parentcf88fcb2ad31b64296d906ef525e76bbe6c3f65e

more number literal syntax is supported. floats still need work


7 files changed, 139 insertions(+), 221 deletions(-)

src/analyze.cpp+1-13
......@@ -640,13 +640,7 @@ static bool num_lit_fits_in_other_type(CodeGen *g, TypeTableEntry *literal_type,
640640 case TypeTableEntryIdStruct:
641641 return false;
642642 case TypeTableEntryIdInt:
643 if (is_num_lit_signed(num_lit)) {
644 if (!other_type->data.integral.is_signed) {
645 return false;
646 }
647
648 return lit_size_in_bits <= other_type->size_in_bits;
649 } else if (is_num_lit_unsigned(num_lit)) {
643 if (is_num_lit_unsigned(num_lit)) {
650644
651645 return lit_size_in_bits <= other_type->size_in_bits;
652646 } else {
......@@ -883,12 +877,6 @@ static TypeTableEntry * resolve_number_literals(CodeGen *g, AstNode *node1, AstN
883877 codegen_num_lit_1->resolved_type = g->builtin_types.entry_f64;
884878 codegen_num_lit_2->resolved_type = g->builtin_types.entry_f64;
885879 return g->builtin_types.entry_f64;
886 } else if (is_num_lit_signed(type1->data.num_lit.kind) &&
887 is_num_lit_signed(type2->data.num_lit.kind))
888 {
889 codegen_num_lit_1->resolved_type = g->builtin_types.entry_i64;
890 codegen_num_lit_2->resolved_type = g->builtin_types.entry_i64;
891 return g->builtin_types.entry_i64;
892880 } else if (is_num_lit_unsigned(type1->data.num_lit.kind) &&
893881 is_num_lit_unsigned(type2->data.num_lit.kind))
894882 {
src/codegen.cpp+1-5
......@@ -1254,13 +1254,9 @@ static const NumLit num_lit_kinds[] = {
12541254 NumLitF32,
12551255 NumLitF64,
12561256 NumLitF128,
1257 NumLitI8,
12581257 NumLitU8,
1259 NumLitI16,
12601258 NumLitU16,
1261 NumLitI32,
12621259 NumLitU32,
1263 NumLitI64,
12641260 NumLitU64,
12651261};
12661262
......@@ -1388,7 +1384,7 @@ static void define_builtin_types(CodeGen *g) {
13881384 }
13891385 {
13901386 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdFloat);
1391 entry->type_ref = LLVMFloatType();
1387 entry->type_ref = LLVMDoubleType();
13921388 buf_init_from_str(&entry->name, "f64");
13931389 entry->size_in_bits = 64;
13941390 entry->align_in_bits = 64;
src/parser.cpp+118-196
......@@ -11,6 +11,7 @@
1111
1212#include <stdarg.h>
1313#include <stdio.h>
14#include <limits.h>
1415
1516
1617static const char *bin_op_str(BinOpType bin_op) {
......@@ -278,9 +279,7 @@ void ast_print(AstNode *node, int indent) {
278279 NumLit num_lit = node->data.number_literal.kind;
279280 const char *name = node_type_str(node->type);
280281 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)) {
284283 fprintf(stderr, "%s %s %" PRIu64 "\n", name, kind_str, node->data.number_literal.data.x_uint);
285284 } else {
286285 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
585584 if (offset_map) offset_map->append(pos);
586585}
587586
588enum ParseNumLitState {
589 ParseNumLitStateStart,
590 ParseNumLitStateBase,
591 ParseNumLitStateDigits,
592 ParseNumLitStateExpectFirstDigit,
593 ParseNumLitStateDecimal,
594 ParseNumLitStateESign,
595 ParseNumLitStateEDigit,
596};
587static 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;
597590
598static 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++) {
612592 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);
640594
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 }
644600
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;
676605 }
677606 }
607 return x;
608}
678609
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();
610static 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;
697617 }
698618
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) {
711626 // 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;
713630
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;
718632
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
722656 return;
723657 }
724658
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
728675 return;
729676 }
730677
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 }
733686
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) {
736696 num_lit->overflow = true;
737697 return;
738698 }
699 if (is_exponent_negative) {
700 exponent -= specified_exponent;
701 } else {
702 exponent += specified_exponent;
703 }
739704 }
740705
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)) {
751713 num_lit->overflow = true;
752714 return;
753715 }
754716
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;
756720 } 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;
768724 }
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;
769733 }
770734}
771735
......@@ -2366,14 +2330,6 @@ const char *num_lit_str(NumLit num_lit) {
23662330 return "f64";
23672331 case NumLitF128:
23682332 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";
23772333 case NumLitU8:
23782334 return "u8";
23792335 case NumLitU16:
......@@ -2388,37 +2344,11 @@ const char *num_lit_str(NumLit num_lit) {
23882344 zig_unreachable();
23892345}
23902346
2391bool 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
24132347bool is_num_lit_unsigned(NumLit num_lit) {
24142348 switch (num_lit) {
24152349 case NumLitF32:
24162350 case NumLitF64:
24172351 case NumLitF128:
2418 case NumLitI8:
2419 case NumLitI16:
2420 case NumLitI32:
2421 case NumLitI64:
24222352 return false;
24232353 case NumLitU8:
24242354 case NumLitU16:
......@@ -2437,10 +2367,6 @@ bool is_num_lit_float(NumLit num_lit) {
24372367 case NumLitF64:
24382368 case NumLitF128:
24392369 return true;
2440 case NumLitI8:
2441 case NumLitI16:
2442 case NumLitI32:
2443 case NumLitI64:
24442370 case NumLitU8:
24452371 case NumLitU16:
24462372 case NumLitU32:
......@@ -2454,17 +2380,13 @@ bool is_num_lit_float(NumLit num_lit) {
24542380
24552381uint64_t num_lit_bit_count(NumLit num_lit) {
24562382 switch (num_lit) {
2457 case NumLitI8:
24582383 case NumLitU8:
24592384 return 8;
2460 case NumLitI16:
24612385 case NumLitU16:
24622386 return 16;
2463 case NumLitI32:
24642387 case NumLitU32:
24652388 case NumLitF32:
24662389 return 32;
2467 case NumLitI64:
24682390 case NumLitU64:
24692391 case NumLitF64:
24702392 return 64;
src/parser.hpp-6
......@@ -273,13 +273,9 @@ enum NumLit {
273273 NumLitF32,
274274 NumLitF64,
275275 NumLitF128,
276 NumLitI8,
277276 NumLitU8,
278 NumLitI16,
279277 NumLitU16,
280 NumLitI32,
281278 NumLitU32,
282 NumLitI64,
283279 NumLitU64,
284280
285281 NumLitCount
......@@ -294,7 +290,6 @@ struct AstNodeNumberLiteral {
294290
295291 union {
296292 uint64_t x_uint;
297 int64_t x_int;
298293 double x_float;
299294 } data;
300295};
......@@ -362,7 +357,6 @@ const char *node_type_str(NodeType node_type);
362357void ast_print(AstNode *node, int indent);
363358
364359const char *num_lit_str(NumLit num_lit);
365bool is_num_lit_signed(NumLit num_lit);
366360bool is_num_lit_unsigned(NumLit num_lit);
367361bool is_num_lit_float(NumLit num_lit);
368362uint64_t num_lit_bit_count(NumLit num_lit);
src/tokenizer.cpp+5-1
......@@ -167,6 +167,9 @@ static void begin_token(Tokenize *t, TokenId id) {
167167 token->start_column = t->column;
168168 token->id = id;
169169 token->start_pos = t->pos;
170 token->radix = 0;
171 token->decimal_point_pos = 0;
172 token->exponent_marker_pos = 0;
170173 t->cur_tok = token;
171174}
172175
......@@ -242,7 +245,8 @@ static bool is_exponent_signifier(uint8_t c, int radix) {
242245 return c == 'e' || c == 'E';
243246 }
244247}
245static int get_digit_value(uint8_t c) {
248
249int get_digit_value(uint8_t c) {
246250 if ('0' <= c && c <= '9') {
247251 return c - '0';
248252 }
src/tokenizer.hpp+1
......@@ -110,5 +110,6 @@ void tokenize(Buf *buf, Tokenization *out_tokenization);
110110void print_tokens(Buf *buf, ZigList<Token> *tokens);
111111
112112bool is_printable(uint8_t c);
113int get_digit_value(uint8_t c);
113114
114115#endif
test/run_tests.cpp+13
......@@ -477,6 +477,19 @@ export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {
477477}
478478 )SOURCE", "OK\n");
479479
480 add_simple_case("number literals", R"SOURCE(
481#link("c")
482extern {
483 fn printf(__format: &const u8, ...) -> i32;
484 fn exit(__status: i32) -> unreachable;
485}
486
487export fn _start() -> unreachable {
488 printf(c"0=%d\n", 0 as i32); // TODO: more tests
489 exit(0);
490}
491 )SOURCE", "0=0\n");
492
480493 add_simple_case("structs", R"SOURCE(
481494use "std.zig";
482495