| ... | @@ -551,8 +551,92 @@ static TypeTableEntry *get_return_type(BlockContext *context) { | ... | @@ -551,8 +551,92 @@ static TypeTableEntry *get_return_type(BlockContext *context) { |
| 551 | return return_type_node->codegen_node->data.type_node.entry; | 551 | return return_type_node->codegen_node->data.type_node.entry; |
| 552 | } | 552 | } |
| 553 | | 553 | |
| 554 | static TypeTableEntry *determine_peer_type_compatibility(CodeGen *g, AstNode *node, | 554 | static bool num_lit_fits_in_other_type(CodeGen *g, TypeTableEntry *literal_type, TypeTableEntry *other_type) { |
| | 555 | NumLit num_lit = literal_type->data.num_lit.kind; |
| | 556 | uint64_t lit_size_in_bits = num_lit_bit_count(num_lit); |
| | 557 | |
| | 558 | switch (other_type->id) { |
| | 559 | case TypeTableEntryIdInvalid: |
| | 560 | case TypeTableEntryIdNumberLiteral: |
| | 561 | zig_unreachable(); |
| | 562 | case TypeTableEntryIdVoid: |
| | 563 | case TypeTableEntryIdBool: |
| | 564 | case TypeTableEntryIdUnreachable: |
| | 565 | case TypeTableEntryIdPointer: |
| | 566 | case TypeTableEntryIdArray: |
| | 567 | case TypeTableEntryIdStruct: |
| | 568 | return false; |
| | 569 | case TypeTableEntryIdInt: |
| | 570 | if (is_num_lit_unsigned(num_lit)) { |
| | 571 | return lit_size_in_bits <= other_type->size_in_bits; |
| | 572 | } else { |
| | 573 | return false; |
| | 574 | } |
| | 575 | case TypeTableEntryIdFloat: |
| | 576 | if (is_num_lit_float(num_lit)) { |
| | 577 | return lit_size_in_bits <= other_type->size_in_bits; |
| | 578 | } else { |
| | 579 | return false; |
| | 580 | } |
| | 581 | } |
| | 582 | zig_unreachable(); |
| | 583 | } |
| | 584 | |
| | 585 | static TypeTableEntry * resolve_rhs_number_literal(CodeGen *g, AstNode *non_literal_node, |
| | 586 | TypeTableEntry *non_literal_type, AstNode *literal_node, TypeTableEntry *literal_type) |
| | 587 | { |
| | 588 | assert(literal_node->codegen_node); |
| | 589 | NumberLiteralNode *codegen_num_lit = &literal_node->codegen_node->data.num_lit_node; |
| | 590 | |
| | 591 | if (num_lit_fits_in_other_type(g, literal_type, non_literal_type)) { |
| | 592 | assert(!codegen_num_lit->resolved_type); |
| | 593 | codegen_num_lit->resolved_type = non_literal_type; |
| | 594 | return non_literal_type; |
| | 595 | } else { |
| | 596 | return nullptr; |
| | 597 | } |
| | 598 | } |
| | 599 | |
| | 600 | static TypeTableEntry * resolve_number_literals(CodeGen *g, AstNode *node1, AstNode *node2, |
| 555 | TypeTableEntry *type1, TypeTableEntry *type2) | 601 | TypeTableEntry *type1, TypeTableEntry *type2) |
| | 602 | { |
| | 603 | if (type1->id == TypeTableEntryIdNumberLiteral && |
| | 604 | type2->id == TypeTableEntryIdNumberLiteral) |
| | 605 | { |
| | 606 | assert(node1->codegen_node); |
| | 607 | assert(node2->codegen_node); |
| | 608 | |
| | 609 | NumberLiteralNode *codegen_num_lit_1 = &node1->codegen_node->data.num_lit_node; |
| | 610 | NumberLiteralNode *codegen_num_lit_2 = &node2->codegen_node->data.num_lit_node; |
| | 611 | |
| | 612 | assert(!codegen_num_lit_1->resolved_type); |
| | 613 | assert(!codegen_num_lit_2->resolved_type); |
| | 614 | |
| | 615 | if (is_num_lit_float(type1->data.num_lit.kind) && |
| | 616 | is_num_lit_float(type2->data.num_lit.kind)) |
| | 617 | { |
| | 618 | codegen_num_lit_1->resolved_type = g->builtin_types.entry_f64; |
| | 619 | codegen_num_lit_2->resolved_type = g->builtin_types.entry_f64; |
| | 620 | return g->builtin_types.entry_f64; |
| | 621 | } else if (is_num_lit_unsigned(type1->data.num_lit.kind) && |
| | 622 | is_num_lit_unsigned(type2->data.num_lit.kind)) |
| | 623 | { |
| | 624 | codegen_num_lit_1->resolved_type = g->builtin_types.entry_u64; |
| | 625 | codegen_num_lit_2->resolved_type = g->builtin_types.entry_u64; |
| | 626 | return g->builtin_types.entry_u64; |
| | 627 | } else { |
| | 628 | return nullptr; |
| | 629 | } |
| | 630 | } else if (type1->id == TypeTableEntryIdNumberLiteral) { |
| | 631 | return resolve_rhs_number_literal(g, node2, type2, node1, type1); |
| | 632 | } else { |
| | 633 | assert(type2->id == TypeTableEntryIdNumberLiteral); |
| | 634 | return resolve_rhs_number_literal(g, node1, type1, node2, type2); |
| | 635 | } |
| | 636 | } |
| | 637 | |
| | 638 | static TypeTableEntry *determine_peer_type_compatibility(CodeGen *g, AstNode *node, |
| | 639 | TypeTableEntry *type1, TypeTableEntry *type2, AstNode *node1, AstNode *node2) |
| 556 | { | 640 | { |
| 557 | if (type1->id == TypeTableEntryIdInvalid || | 641 | if (type1->id == TypeTableEntryIdInvalid || |
| 558 | type2->id == TypeTableEntryIdInvalid) | 642 | type2->id == TypeTableEntryIdInvalid) |
| ... | @@ -576,48 +660,23 @@ static TypeTableEntry *determine_peer_type_compatibility(CodeGen *g, AstNode *no | ... | @@ -576,48 +660,23 @@ static TypeTableEntry *determine_peer_type_compatibility(CodeGen *g, AstNode *no |
| 576 | type1 == type2) | 660 | type1 == type2) |
| 577 | { | 661 | { |
| 578 | return type1; | 662 | return type1; |
| | 663 | } else if (type1->id == TypeTableEntryIdNumberLiteral || |
| | 664 | type2->id == TypeTableEntryIdNumberLiteral) |
| | 665 | { |
| | 666 | TypeTableEntry *resolved_type = resolve_number_literals(g, node1, node2, type1, type2); |
| | 667 | if (resolved_type) |
| | 668 | return resolved_type; |
| 579 | } else if (type1 == type2) { | 669 | } else if (type1 == type2) { |
| 580 | return type1; | 670 | return type1; |
| 581 | } | 671 | } |
| 582 | | 672 | |
| 583 | add_node_error(g, node, | 673 | add_node_error(g, node, |
| 584 | buf_sprintf("ambiguous expression type: '%s' vs '%s'", | 674 | buf_sprintf("incompatible types: '%s' and '%s'", |
| 585 | buf_ptr(&type1->name), buf_ptr(&type2->name))); | 675 | buf_ptr(&type1->name), buf_ptr(&type2->name))); |
| 586 | | 676 | |
| 587 | return g->builtin_types.entry_invalid; | 677 | return g->builtin_types.entry_invalid; |
| 588 | } | 678 | } |
| 589 | | 679 | |
| 590 | static bool num_lit_fits_in_other_type(CodeGen *g, TypeTableEntry *literal_type, TypeTableEntry *other_type) { | | |
| 591 | NumLit num_lit = literal_type->data.num_lit.kind; | | |
| 592 | uint64_t lit_size_in_bits = num_lit_bit_count(num_lit); | | |
| 593 | | | |
| 594 | switch (other_type->id) { | | |
| 595 | case TypeTableEntryIdInvalid: | | |
| 596 | case TypeTableEntryIdNumberLiteral: | | |
| 597 | zig_unreachable(); | | |
| 598 | case TypeTableEntryIdVoid: | | |
| 599 | case TypeTableEntryIdBool: | | |
| 600 | case TypeTableEntryIdUnreachable: | | |
| 601 | case TypeTableEntryIdPointer: | | |
| 602 | case TypeTableEntryIdArray: | | |
| 603 | case TypeTableEntryIdStruct: | | |
| 604 | return false; | | |
| 605 | case TypeTableEntryIdInt: | | |
| 606 | if (is_num_lit_unsigned(num_lit)) { | | |
| 607 | return lit_size_in_bits <= other_type->size_in_bits; | | |
| 608 | } else { | | |
| 609 | return false; | | |
| 610 | } | | |
| 611 | case TypeTableEntryIdFloat: | | |
| 612 | if (is_num_lit_float(num_lit)) { | | |
| 613 | return lit_size_in_bits <= other_type->size_in_bits; | | |
| 614 | } else { | | |
| 615 | return false; | | |
| 616 | } | | |
| 617 | } | | |
| 618 | zig_unreachable(); | | |
| 619 | } | | |
| 620 | | | |
| 621 | static TypeTableEntry *resolve_type_compatibility(CodeGen *g, BlockContext *context, AstNode *node, | 680 | static TypeTableEntry *resolve_type_compatibility(CodeGen *g, BlockContext *context, AstNode *node, |
| 622 | TypeTableEntry *expected_type, TypeTableEntry *actual_type) | 681 | TypeTableEntry *expected_type, TypeTableEntry *actual_type) |
| 623 | { | 682 | { |
| ... | @@ -676,7 +735,7 @@ static TypeTableEntry *resolve_peer_type_compatibility(CodeGen *g, BlockContext | ... | @@ -676,7 +735,7 @@ static TypeTableEntry *resolve_peer_type_compatibility(CodeGen *g, BlockContext |
| 676 | assert(type1); | 735 | assert(type1); |
| 677 | assert(type2); | 736 | assert(type2); |
| 678 | | 737 | |
| 679 | TypeTableEntry *parent_type = determine_peer_type_compatibility(g, parent_node, type1, type2); | 738 | TypeTableEntry *parent_type = determine_peer_type_compatibility(g, parent_node, type1, type2, child1, child2); |
| 680 | | 739 | |
| 681 | if (parent_type->id == TypeTableEntryIdInvalid) { | 740 | if (parent_type->id == TypeTableEntryIdInvalid) { |
| 682 | return parent_type; | 741 | return parent_type; |
| ... | @@ -928,60 +987,6 @@ static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, B | ... | @@ -928,60 +987,6 @@ static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, B |
| 928 | } | 987 | } |
| 929 | } | 988 | } |
| 930 | | 989 | |
| 931 | static TypeTableEntry * resolve_rhs_number_literal(CodeGen *g, AstNode *non_literal_node, | | |
| 932 | TypeTableEntry *non_literal_type, AstNode *literal_node, TypeTableEntry *literal_type) | | |
| 933 | { | | |
| 934 | assert(literal_node->codegen_node); | | |
| 935 | NumberLiteralNode *codegen_num_lit = &literal_node->codegen_node->data.num_lit_node; | | |
| 936 | | | |
| 937 | if (num_lit_fits_in_other_type(g, literal_type, non_literal_type)) { | | |
| 938 | assert(!codegen_num_lit->resolved_type); | | |
| 939 | codegen_num_lit->resolved_type = non_literal_type; | | |
| 940 | return non_literal_type; | | |
| 941 | } else { | | |
| 942 | return nullptr; | | |
| 943 | } | | |
| 944 | } | | |
| 945 | | | |
| 946 | static TypeTableEntry * resolve_number_literals(CodeGen *g, AstNode *node1, AstNode *node2) { | | |
| 947 | TypeTableEntry *type1 = node1->codegen_node->expr_node.type_entry; | | |
| 948 | TypeTableEntry *type2 = node2->codegen_node->expr_node.type_entry; | | |
| 949 | | | |
| 950 | if (type1->id == TypeTableEntryIdNumberLiteral && | | |
| 951 | type2->id == TypeTableEntryIdNumberLiteral) | | |
| 952 | { | | |
| 953 | assert(node1->codegen_node); | | |
| 954 | assert(node2->codegen_node); | | |
| 955 | | | |
| 956 | NumberLiteralNode *codegen_num_lit_1 = &node1->codegen_node->data.num_lit_node; | | |
| 957 | NumberLiteralNode *codegen_num_lit_2 = &node2->codegen_node->data.num_lit_node; | | |
| 958 | | | |
| 959 | assert(!codegen_num_lit_1->resolved_type); | | |
| 960 | assert(!codegen_num_lit_2->resolved_type); | | |
| 961 | | | |
| 962 | if (is_num_lit_float(type1->data.num_lit.kind) && | | |
| 963 | is_num_lit_float(type2->data.num_lit.kind)) | | |
| 964 | { | | |
| 965 | codegen_num_lit_1->resolved_type = g->builtin_types.entry_f64; | | |
| 966 | codegen_num_lit_2->resolved_type = g->builtin_types.entry_f64; | | |
| 967 | return g->builtin_types.entry_f64; | | |
| 968 | } else if (is_num_lit_unsigned(type1->data.num_lit.kind) && | | |
| 969 | is_num_lit_unsigned(type2->data.num_lit.kind)) | | |
| 970 | { | | |
| 971 | codegen_num_lit_1->resolved_type = g->builtin_types.entry_u64; | | |
| 972 | codegen_num_lit_2->resolved_type = g->builtin_types.entry_u64; | | |
| 973 | return g->builtin_types.entry_u64; | | |
| 974 | } else { | | |
| 975 | return nullptr; | | |
| 976 | } | | |
| 977 | } else if (type1->id == TypeTableEntryIdNumberLiteral) { | | |
| 978 | return resolve_rhs_number_literal(g, node2, type2, node1, type1); | | |
| 979 | } else { | | |
| 980 | assert(type2->id == TypeTableEntryIdNumberLiteral); | | |
| 981 | return resolve_rhs_number_literal(g, node1, type1, node2, type2); | | |
| 982 | } | | |
| 983 | } | | |
| 984 | | | |
| 985 | static TypeTableEntry *analyze_bin_op_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, | 990 | static TypeTableEntry *analyze_bin_op_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, |
| 986 | TypeTableEntry *expected_type, AstNode *node) | 991 | TypeTableEntry *expected_type, AstNode *node) |
| 987 | { | 992 | { |
| ... | @@ -1052,31 +1057,9 @@ static TypeTableEntry *analyze_bin_op_expr(CodeGen *g, ImportTableEntry *import, | ... | @@ -1052,31 +1057,9 @@ static TypeTableEntry *analyze_bin_op_expr(CodeGen *g, ImportTableEntry *import, |
| 1052 | AstNode *op2 = node->data.bin_op_expr.op2; | 1057 | AstNode *op2 = node->data.bin_op_expr.op2; |
| 1053 | TypeTableEntry *lhs_type = analyze_expression(g, import, context, nullptr, op1); | 1058 | TypeTableEntry *lhs_type = analyze_expression(g, import, context, nullptr, op1); |
| 1054 | TypeTableEntry *rhs_type = analyze_expression(g, import, context, nullptr, op2); | 1059 | TypeTableEntry *rhs_type = analyze_expression(g, import, context, nullptr, op2); |
| 1055 | bool cmp_ok = false; | 1060 | |
| 1056 | if (lhs_type->id == TypeTableEntryIdInvalid || rhs_type->id == TypeTableEntryIdInvalid) { | 1061 | resolve_peer_type_compatibility(g, context, node, op1, op2, lhs_type, rhs_type); |
| 1057 | cmp_ok = true; | 1062 | |
| 1058 | } else if (lhs_type->id == TypeTableEntryIdNumberLiteral || | | |
| 1059 | rhs_type->id == TypeTableEntryIdNumberLiteral) | | |
| 1060 | { | | |
| 1061 | cmp_ok = resolve_number_literals(g, op1, op2); | | |
| 1062 | } else if (lhs_type->id == TypeTableEntryIdInt) { | | |
| 1063 | if (rhs_type->id == TypeTableEntryIdInt && | | |
| 1064 | lhs_type->data.integral.is_signed == rhs_type->data.integral.is_signed && | | |
| 1065 | lhs_type->size_in_bits == rhs_type->size_in_bits) | | |
| 1066 | { | | |
| 1067 | cmp_ok = true; | | |
| 1068 | } | | |
| 1069 | } else if (lhs_type->id == TypeTableEntryIdFloat) { | | |
| 1070 | if (rhs_type->id == TypeTableEntryIdFloat && | | |
| 1071 | lhs_type->size_in_bits == rhs_type->size_in_bits) | | |
| 1072 | { | | |
| 1073 | cmp_ok = true; | | |
| 1074 | } | | |
| 1075 | } | | |
| 1076 | if (!cmp_ok) { | | |
| 1077 | add_node_error(g, node, buf_sprintf("unable to compare '%s' with '%s'", | | |
| 1078 | buf_ptr(&lhs_type->name), buf_ptr(&rhs_type->name))); | | |
| 1079 | } | | |
| 1080 | return g->builtin_types.entry_bool; | 1063 | return g->builtin_types.entry_bool; |
| 1081 | } | 1064 | } |
| 1082 | case BinOpTypeBinOr: | 1065 | case BinOpTypeBinOr: |
| ... | @@ -1104,34 +1087,7 @@ static TypeTableEntry *analyze_bin_op_expr(CodeGen *g, ImportTableEntry *import, | ... | @@ -1104,34 +1087,7 @@ static TypeTableEntry *analyze_bin_op_expr(CodeGen *g, ImportTableEntry *import, |
| 1104 | TypeTableEntry *lhs_type = analyze_expression(g, import, context, expected_type, op1); | 1087 | TypeTableEntry *lhs_type = analyze_expression(g, import, context, expected_type, op1); |
| 1105 | TypeTableEntry *rhs_type = analyze_expression(g, import, context, expected_type, op2); | 1088 | TypeTableEntry *rhs_type = analyze_expression(g, import, context, expected_type, op2); |
| 1106 | | 1089 | |
| 1107 | TypeTableEntry *return_type = nullptr; | 1090 | return resolve_peer_type_compatibility(g, context, node, op1, op2, lhs_type, rhs_type); |
| 1108 | | | |
| 1109 | if (lhs_type->id == TypeTableEntryIdInvalid || rhs_type->id == TypeTableEntryIdInvalid) { | | |
| 1110 | return_type = g->builtin_types.entry_invalid; | | |
| 1111 | } else if (lhs_type->id == TypeTableEntryIdNumberLiteral || | | |
| 1112 | rhs_type->id == TypeTableEntryIdNumberLiteral) | | |
| 1113 | { | | |
| 1114 | return_type = resolve_number_literals(g, op1, op2); | | |
| 1115 | } else if (lhs_type->id == TypeTableEntryIdInt && | | |
| 1116 | lhs_type == rhs_type) | | |
| 1117 | { | | |
| 1118 | return_type = lhs_type; | | |
| 1119 | } else if (lhs_type->id == TypeTableEntryIdFloat && | | |
| 1120 | lhs_type == rhs_type) | | |
| 1121 | { | | |
| 1122 | return_type = lhs_type; | | |
| 1123 | } | | |
| 1124 | if (!return_type) { | | |
| 1125 | if (node->data.bin_op_expr.bin_op == BinOpTypeAdd) { | | |
| 1126 | add_node_error(g, node, buf_sprintf("unable to add '%s' and '%s'", | | |
| 1127 | buf_ptr(&lhs_type->name), buf_ptr(&rhs_type->name))); | | |
| 1128 | } else { | | |
| 1129 | add_node_error(g, node, buf_sprintf("unable to subtract '%s' and '%s'", | | |
| 1130 | buf_ptr(&lhs_type->name), buf_ptr(&rhs_type->name))); | | |
| 1131 | } | | |
| 1132 | return g->builtin_types.entry_invalid; | | |
| 1133 | } | | |
| 1134 | return return_type; | | |
| 1135 | } | 1091 | } |
| 1136 | case BinOpTypeMult: | 1092 | case BinOpTypeMult: |
| 1137 | case BinOpTypeDiv: | 1093 | case BinOpTypeDiv: |