| ... | ... | @@ -103,7 +103,8 @@ TypeTableEntry *new_type_table_entry(TypeTableEntryId id) { |
| 103 | 103 | case TypeTableEntryIdFloat: |
| 104 | 104 | case TypeTableEntryIdPointer: |
| 105 | 105 | case TypeTableEntryIdArray: |
| 106 | | case TypeTableEntryIdNumberLiteral: |
| 106 | case TypeTableEntryIdNumLitFloat: |
| 107 | case TypeTableEntryIdNumLitInt: |
| 107 | 108 | case TypeTableEntryIdMaybe: |
| 108 | 109 | case TypeTableEntryIdFn: |
| 109 | 110 | case TypeTableEntryIdError: |
| ... | ... | @@ -121,24 +122,20 @@ TypeTableEntry *new_type_table_entry(TypeTableEntryId id) { |
| 121 | 122 | return entry; |
| 122 | 123 | } |
| 123 | 124 | |
| 124 | | static NumLit get_number_literal_kind_unsigned(uint64_t x) { |
| 125 | static int bits_needed_for_unsigned(uint64_t x) { |
| 125 | 126 | if (x <= UINT8_MAX) { |
| 126 | | return NumLitU8; |
| 127 | return 8; |
| 127 | 128 | } else if (x <= UINT16_MAX) { |
| 128 | | return NumLitU16; |
| 129 | return 16; |
| 129 | 130 | } else if (x <= UINT32_MAX) { |
| 130 | | return NumLitU32; |
| 131 | return 32; |
| 131 | 132 | } else { |
| 132 | | return NumLitU64; |
| 133 | return 64; |
| 133 | 134 | } |
| 134 | 135 | } |
| 135 | 136 | |
| 136 | | static TypeTableEntry *get_number_literal_type_unsigned(CodeGen *g, uint64_t x) { |
| 137 | | return g->num_lit_types[get_number_literal_kind_unsigned(x)]; |
| 138 | | } |
| 139 | | |
| 140 | | static TypeTableEntry *get_int_type_unsigned(CodeGen *g, uint64_t x) { |
| 141 | | return get_int_type(g, false, num_lit_bit_count(get_number_literal_kind_unsigned(x))); |
| 137 | static TypeTableEntry *get_smallest_unsigned_int_type(CodeGen *g, uint64_t x) { |
| 138 | return get_int_type(g, false, bits_needed_for_unsigned(x)); |
| 142 | 139 | } |
| 143 | 140 | |
| 144 | 141 | TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const) { |
| ... | ... | @@ -660,10 +657,9 @@ static void resolve_enum_type(CodeGen *g, ImportTableEntry *import, TypeTableEnt |
| 660 | 657 | if (!enum_type->data.enumeration.is_invalid) { |
| 661 | 658 | enum_type->data.enumeration.gen_field_count = gen_field_index; |
| 662 | 659 | |
| 663 | | uint64_t tag_size_in_bits = num_lit_bit_count(get_number_literal_kind_unsigned(field_count)); |
| 664 | | enum_type->align_in_bits = tag_size_in_bits; |
| 665 | | enum_type->size_in_bits = tag_size_in_bits + biggest_union_member_size_in_bits; |
| 666 | | TypeTableEntry *tag_type_entry = get_int_type_unsigned(g, field_count); |
| 660 | TypeTableEntry *tag_type_entry = get_smallest_unsigned_int_type(g, field_count); |
| 661 | enum_type->align_in_bits = tag_type_entry->size_in_bits; |
| 662 | enum_type->size_in_bits = tag_type_entry->size_in_bits + biggest_union_member_size_in_bits; |
| 667 | 663 | enum_type->data.enumeration.tag_type = tag_type_entry; |
| 668 | 664 | |
| 669 | 665 | if (biggest_union_member) { |
| ... | ... | @@ -1048,136 +1044,105 @@ static TypeTableEntry *get_return_type(BlockContext *context) { |
| 1048 | 1044 | return unwrapped_node_type(return_type_node); |
| 1049 | 1045 | } |
| 1050 | 1046 | |
| 1051 | | static bool num_lit_fits_in_other_type(CodeGen *g, TypeTableEntry *literal_type, TypeTableEntry *other_type) { |
| 1052 | | NumLit num_lit = literal_type->data.num_lit.kind; |
| 1053 | | uint64_t lit_size_in_bits = num_lit_bit_count(num_lit); |
| 1054 | | |
| 1055 | | switch (other_type->id) { |
| 1056 | | case TypeTableEntryIdInvalid: |
| 1057 | | case TypeTableEntryIdNumberLiteral: |
| 1058 | | zig_unreachable(); |
| 1059 | | case TypeTableEntryIdVoid: |
| 1060 | | case TypeTableEntryIdBool: |
| 1061 | | case TypeTableEntryIdUnreachable: |
| 1062 | | case TypeTableEntryIdPointer: |
| 1063 | | case TypeTableEntryIdArray: |
| 1064 | | case TypeTableEntryIdStruct: |
| 1065 | | case TypeTableEntryIdEnum: |
| 1066 | | case TypeTableEntryIdMetaType: |
| 1067 | | case TypeTableEntryIdFn: |
| 1068 | | case TypeTableEntryIdError: |
| 1069 | | return false; |
| 1070 | | case TypeTableEntryIdInt: |
| 1071 | | if (is_num_lit_unsigned(num_lit)) { |
| 1072 | | return lit_size_in_bits <= other_type->size_in_bits; |
| 1073 | | } else { |
| 1074 | | return false; |
| 1075 | | } |
| 1076 | | case TypeTableEntryIdFloat: |
| 1077 | | if (is_num_lit_float(num_lit)) { |
| 1078 | | return lit_size_in_bits <= other_type->size_in_bits; |
| 1079 | | } else if (other_type->size_in_bits == 32) { |
| 1080 | | return lit_size_in_bits < 24; |
| 1081 | | } else if (other_type->size_in_bits == 64) { |
| 1082 | | return lit_size_in_bits < 53; |
| 1083 | | } else { |
| 1084 | | return false; |
| 1085 | | } |
| 1086 | | case TypeTableEntryIdMaybe: |
| 1087 | | return false; |
| 1047 | static bool num_lit_fits_in_other_type(CodeGen *g, AstNode *literal_node, TypeTableEntry *other_type) { |
| 1048 | Expr *expr = get_resolved_expr(literal_node); |
| 1049 | ConstExprValue *const_val = &expr->const_val; |
| 1050 | assert(const_val->ok); |
| 1051 | if (other_type->id == TypeTableEntryIdFloat) { |
| 1052 | expr->resolved_type = other_type; |
| 1053 | return true; |
| 1054 | } else if (other_type->id == TypeTableEntryIdInt && |
| 1055 | const_val->data.x_bignum.kind == BigNumKindInt) |
| 1056 | { |
| 1057 | if (bignum_fits_in_bits(&const_val->data.x_bignum, other_type->size_in_bits, |
| 1058 | other_type->data.integral.is_signed)) |
| 1059 | { |
| 1060 | expr->resolved_type = other_type; |
| 1061 | return true; |
| 1062 | } |
| 1063 | } else if (other_type->id == TypeTableEntryIdNumLitFloat || |
| 1064 | other_type->id == TypeTableEntryIdNumLitInt) |
| 1065 | { |
| 1066 | return true; |
| 1088 | 1067 | } |
| 1089 | | zig_unreachable(); |
| 1090 | | } |
| 1091 | | |
| 1092 | | static TypeTableEntry *resolve_rhs_number_literal(CodeGen *g, AstNode *non_literal_node, |
| 1093 | | TypeTableEntry *non_literal_type, AstNode *literal_node, TypeTableEntry *literal_type) |
| 1094 | | { |
| 1095 | | NumLitCodeGen *num_lit_codegen = get_resolved_num_lit(literal_node); |
| 1096 | 1068 | |
| 1097 | | if (non_literal_type && num_lit_fits_in_other_type(g, literal_type, non_literal_type)) { |
| 1098 | | assert(!num_lit_codegen->resolved_type); |
| 1099 | | num_lit_codegen->resolved_type = non_literal_type; |
| 1100 | | return non_literal_type; |
| 1101 | | } else { |
| 1102 | | return nullptr; |
| 1103 | | } |
| 1069 | add_node_error(g, literal_node, |
| 1070 | buf_sprintf("value %s cannot be represented in type '%s'", |
| 1071 | buf_ptr(bignum_to_buf(&const_val->data.x_bignum)), |
| 1072 | buf_ptr(&other_type->name))); |
| 1073 | return false; |
| 1104 | 1074 | } |
| 1105 | 1075 | |
| 1106 | | static TypeTableEntry * resolve_number_literals(CodeGen *g, AstNode *node1, AstNode *node2, |
| 1107 | | TypeTableEntry *type1, TypeTableEntry *type2) |
| 1076 | static TypeTableEntry *determine_peer_type_compatibility(CodeGen *g, AstNode *parent_source_node, |
| 1077 | AstNode **child_nodes, TypeTableEntry **child_types, int child_count) |
| 1108 | 1078 | { |
| 1109 | | if (type1->id == TypeTableEntryIdNumberLiteral && |
| 1110 | | type2->id == TypeTableEntryIdNumberLiteral) |
| 1111 | | { |
| 1112 | | NumLitCodeGen *codegen_num_lit_1 = get_resolved_num_lit(node1); |
| 1113 | | NumLitCodeGen *codegen_num_lit_2 = get_resolved_num_lit(node2); |
| 1114 | | |
| 1115 | | assert(!codegen_num_lit_1->resolved_type); |
| 1116 | | assert(!codegen_num_lit_2->resolved_type); |
| 1117 | | |
| 1118 | | if (is_num_lit_float(type1->data.num_lit.kind) && |
| 1119 | | is_num_lit_float(type2->data.num_lit.kind)) |
| 1079 | TypeTableEntry *prev_type = child_types[0]; |
| 1080 | AstNode *prev_node = child_nodes[0]; |
| 1081 | if (prev_type->id == TypeTableEntryIdInvalid) { |
| 1082 | return prev_type; |
| 1083 | } |
| 1084 | for (int i = 1; i < child_count; i += 1) { |
| 1085 | TypeTableEntry *cur_type = child_types[i]; |
| 1086 | AstNode *cur_node = child_nodes[i]; |
| 1087 | if (cur_type->id == TypeTableEntryIdInvalid) { |
| 1088 | return cur_type; |
| 1089 | } else if (prev_type->id == TypeTableEntryIdUnreachable) { |
| 1090 | prev_type = cur_type; |
| 1091 | prev_node = cur_node; |
| 1092 | } else if (cur_type->id == TypeTableEntryIdUnreachable) { |
| 1093 | continue; |
| 1094 | } else if (prev_type->id == TypeTableEntryIdInt && |
| 1095 | cur_type->id == TypeTableEntryIdInt && |
| 1096 | prev_type->data.integral.is_signed == cur_type->data.integral.is_signed) |
| 1097 | { |
| 1098 | if (cur_type->size_in_bits > prev_type->size_in_bits) { |
| 1099 | prev_type = cur_type; |
| 1100 | prev_node = cur_node; |
| 1101 | } |
| 1102 | } else if (prev_type->id == TypeTableEntryIdFloat && |
| 1103 | cur_type->id == TypeTableEntryIdFloat) |
| 1104 | { |
| 1105 | if (cur_type->size_in_bits > prev_type->size_in_bits) { |
| 1106 | prev_type = cur_type; |
| 1107 | prev_node = cur_node; |
| 1108 | } |
| 1109 | } else if (prev_type->id == TypeTableEntryIdNumLitFloat && |
| 1110 | cur_type->id == TypeTableEntryIdNumLitFloat) |
| 1111 | { |
| 1112 | continue; |
| 1113 | } else if (prev_type->id == TypeTableEntryIdNumLitInt && |
| 1114 | cur_type->id == TypeTableEntryIdNumLitInt) |
| 1120 | 1115 | { |
| 1121 | | codegen_num_lit_1->resolved_type = g->builtin_types.entry_f64; |
| 1122 | | codegen_num_lit_2->resolved_type = g->builtin_types.entry_f64; |
| 1123 | | return g->builtin_types.entry_f64; |
| 1124 | | } else if (is_num_lit_unsigned(type1->data.num_lit.kind) && |
| 1125 | | is_num_lit_unsigned(type2->data.num_lit.kind)) |
| 1116 | continue; |
| 1117 | } else if (prev_type->id == TypeTableEntryIdNumLitInt || |
| 1118 | prev_type->id == TypeTableEntryIdNumLitFloat) |
| 1119 | { |
| 1120 | if (num_lit_fits_in_other_type(g, prev_node, cur_type)) { |
| 1121 | prev_type = cur_type; |
| 1122 | prev_node = cur_node; |
| 1123 | continue; |
| 1124 | } else { |
| 1125 | return g->builtin_types.entry_invalid; |
| 1126 | } |
| 1127 | } else if (cur_type->id == TypeTableEntryIdNumLitInt || |
| 1128 | cur_type->id == TypeTableEntryIdNumLitFloat) |
| 1126 | 1129 | { |
| 1127 | | codegen_num_lit_1->resolved_type = g->builtin_types.entry_u64; |
| 1128 | | codegen_num_lit_2->resolved_type = g->builtin_types.entry_u64; |
| 1129 | | return g->builtin_types.entry_u64; |
| 1130 | if (num_lit_fits_in_other_type(g, cur_node, prev_type)) { |
| 1131 | continue; |
| 1132 | } else { |
| 1133 | return g->builtin_types.entry_invalid; |
| 1134 | } |
| 1135 | } else if (prev_type == cur_type) { |
| 1136 | continue; |
| 1130 | 1137 | } else { |
| 1131 | | return nullptr; |
| 1132 | | } |
| 1133 | | } else if (type1->id == TypeTableEntryIdNumberLiteral) { |
| 1134 | | return resolve_rhs_number_literal(g, node2, type2, node1, type1); |
| 1135 | | } else { |
| 1136 | | assert(type2->id == TypeTableEntryIdNumberLiteral); |
| 1137 | | return resolve_rhs_number_literal(g, node1, type1, node2, type2); |
| 1138 | | } |
| 1139 | | } |
| 1138 | add_node_error(g, parent_source_node, |
| 1139 | buf_sprintf("incompatible types: '%s' and '%s'", |
| 1140 | buf_ptr(&prev_type->name), buf_ptr(&cur_type->name))); |
| 1140 | 1141 | |
| 1141 | | static TypeTableEntry *determine_peer_type_compatibility(CodeGen *g, AstNode *node, |
| 1142 | | TypeTableEntry *type1, TypeTableEntry *type2, AstNode *node1, AstNode *node2) |
| 1143 | | { |
| 1144 | | if (type1->id == TypeTableEntryIdInvalid || |
| 1145 | | type2->id == TypeTableEntryIdInvalid) |
| 1146 | | { |
| 1147 | | return type1; |
| 1148 | | } else if (type1->id == TypeTableEntryIdUnreachable) { |
| 1149 | | return type2; |
| 1150 | | } else if (type2->id == TypeTableEntryIdUnreachable) { |
| 1151 | | return type1; |
| 1152 | | } else if (type1->id == TypeTableEntryIdInt && |
| 1153 | | type2->id == TypeTableEntryIdInt && |
| 1154 | | type1->data.integral.is_signed == type2->data.integral.is_signed) |
| 1155 | | { |
| 1156 | | return (type1->size_in_bits > type2->size_in_bits) ? type1 : type2; |
| 1157 | | } else if (type1->id == TypeTableEntryIdFloat && |
| 1158 | | type2->id == TypeTableEntryIdFloat) |
| 1159 | | { |
| 1160 | | return (type1->size_in_bits > type2->size_in_bits) ? type1 : type2; |
| 1161 | | } else if (type1->id == TypeTableEntryIdArray && |
| 1162 | | type2->id == TypeTableEntryIdArray && |
| 1163 | | type1 == type2) |
| 1164 | | { |
| 1165 | | return type1; |
| 1166 | | } else if (type1->id == TypeTableEntryIdNumberLiteral || |
| 1167 | | type2->id == TypeTableEntryIdNumberLiteral) |
| 1168 | | { |
| 1169 | | TypeTableEntry *resolved_type = resolve_number_literals(g, node1, node2, type1, type2); |
| 1170 | | if (resolved_type) |
| 1171 | | return resolved_type; |
| 1172 | | } else if (type1 == type2) { |
| 1173 | | return type1; |
| 1142 | return g->builtin_types.entry_invalid; |
| 1143 | } |
| 1174 | 1144 | } |
| 1175 | | |
| 1176 | | add_node_error(g, node, |
| 1177 | | buf_sprintf("incompatible types: '%s' and '%s'", |
| 1178 | | buf_ptr(&type1->name), buf_ptr(&type2->name))); |
| 1179 | | |
| 1180 | | return g->builtin_types.entry_invalid; |
| 1145 | return prev_type; |
| 1181 | 1146 | } |
| 1182 | 1147 | |
| 1183 | 1148 | static TypeTableEntry *resolve_type_compatibility(CodeGen *g, BlockContext *context, AstNode *node, |
| ... | ... | @@ -1192,16 +1157,6 @@ static TypeTableEntry *resolve_type_compatibility(CodeGen *g, BlockContext *cont |
| 1192 | 1157 | if (actual_type->id == TypeTableEntryIdUnreachable) |
| 1193 | 1158 | return actual_type; // sorry toots; gotta run. good luck with that expected type. |
| 1194 | 1159 | |
| 1195 | | if (actual_type->id == TypeTableEntryIdNumberLiteral && |
| 1196 | | num_lit_fits_in_other_type(g, actual_type, expected_type)) |
| 1197 | | { |
| 1198 | | NumLitCodeGen *num_lit_code_gen = get_resolved_num_lit(node); |
| 1199 | | assert(!num_lit_code_gen->resolved_type || |
| 1200 | | num_lit_code_gen->resolved_type == expected_type); |
| 1201 | | num_lit_code_gen->resolved_type = expected_type; |
| 1202 | | return expected_type; |
| 1203 | | } |
| 1204 | | |
| 1205 | 1160 | if (expected_type->id == TypeTableEntryIdMaybe && |
| 1206 | 1161 | actual_type->id == TypeTableEntryIdMaybe) |
| 1207 | 1162 | { |
| ... | ... | @@ -1283,6 +1238,16 @@ static TypeTableEntry *resolve_type_compatibility(CodeGen *g, BlockContext *cont |
| 1283 | 1238 | return expected_type; |
| 1284 | 1239 | } |
| 1285 | 1240 | |
| 1241 | if ((actual_type->id == TypeTableEntryIdNumLitFloat || |
| 1242 | actual_type->id == TypeTableEntryIdNumLitInt)) |
| 1243 | { |
| 1244 | if (num_lit_fits_in_other_type(g, node, expected_type)) { |
| 1245 | return expected_type; |
| 1246 | } else { |
| 1247 | return g->builtin_types.entry_invalid; |
| 1248 | } |
| 1249 | } |
| 1250 | |
| 1286 | 1251 | add_node_error(g, first_executing_node(node), |
| 1287 | 1252 | buf_sprintf("expected type '%s', got '%s'", |
| 1288 | 1253 | buf_ptr(&expected_type->name), |
| ... | ... | @@ -1292,23 +1257,23 @@ static TypeTableEntry *resolve_type_compatibility(CodeGen *g, BlockContext *cont |
| 1292 | 1257 | } |
| 1293 | 1258 | |
| 1294 | 1259 | static TypeTableEntry *resolve_peer_type_compatibility(CodeGen *g, BlockContext *block_context, |
| 1295 | | AstNode *parent_node, |
| 1296 | | AstNode *child1, AstNode *child2, |
| 1297 | | TypeTableEntry *type1, TypeTableEntry *type2) |
| 1260 | AstNode *parent_source_node, |
| 1261 | AstNode **child_nodes, TypeTableEntry **child_types, int child_count) |
| 1298 | 1262 | { |
| 1299 | | assert(type1); |
| 1300 | | assert(type2); |
| 1263 | assert(child_count > 0); |
| 1301 | 1264 | |
| 1302 | | TypeTableEntry *parent_type = determine_peer_type_compatibility(g, parent_node, type1, type2, child1, child2); |
| 1265 | TypeTableEntry *expected_type = determine_peer_type_compatibility(g, parent_source_node, |
| 1266 | child_nodes, child_types, child_count); |
| 1303 | 1267 | |
| 1304 | | if (parent_type->id == TypeTableEntryIdInvalid) { |
| 1305 | | return parent_type; |
| 1268 | if (expected_type->id == TypeTableEntryIdInvalid) { |
| 1269 | return expected_type; |
| 1306 | 1270 | } |
| 1307 | 1271 | |
| 1308 | | resolve_type_compatibility(g, block_context, child1, parent_type, type1); |
| 1309 | | resolve_type_compatibility(g, block_context, child2, parent_type, type2); |
| 1272 | for (int i = 0; i < child_count; i += 1) { |
| 1273 | resolve_type_compatibility(g, block_context, child_nodes[i], expected_type, child_types[i]); |
| 1274 | } |
| 1310 | 1275 | |
| 1311 | | return parent_type; |
| 1276 | return expected_type; |
| 1312 | 1277 | } |
| 1313 | 1278 | |
| 1314 | 1279 | BlockContext *new_block_context(AstNode *node, BlockContext *parent) { |
| ... | ... | @@ -1732,12 +1697,58 @@ static TypeTableEntry *resolve_expr_const_val_as_unsigned_num_lit(CodeGen *g, As |
| 1732 | 1697 | { |
| 1733 | 1698 | Expr *expr = get_resolved_expr(node); |
| 1734 | 1699 | expr->const_val.ok = true; |
| 1735 | | expr->const_val.data.x_uint = x; |
| 1736 | | TypeTableEntry *num_lit_type = get_number_literal_type_unsigned(g, x); |
| 1737 | | TypeTableEntry *resolved_type = resolve_rhs_number_literal(g, nullptr, expected_type, node, num_lit_type); |
| 1738 | | return resolved_type ? resolved_type : num_lit_type; |
| 1700 | |
| 1701 | bignum_init_unsigned(&expr->const_val.data.x_bignum, x); |
| 1702 | |
| 1703 | if (expected_type) { |
| 1704 | if (expected_type->id == TypeTableEntryIdMaybe) { |
| 1705 | return g->builtin_types.entry_num_lit_int; |
| 1706 | } else { |
| 1707 | num_lit_fits_in_other_type(g, node, expected_type); |
| 1708 | return expected_type; |
| 1709 | } |
| 1710 | } else { |
| 1711 | return g->builtin_types.entry_num_lit_int; |
| 1712 | } |
| 1713 | } |
| 1714 | |
| 1715 | static TypeTableEntry *resolve_expr_const_val_as_float_num_lit(CodeGen *g, AstNode *node, |
| 1716 | TypeTableEntry *expected_type, double x) |
| 1717 | { |
| 1718 | Expr *expr = get_resolved_expr(node); |
| 1719 | expr->const_val.ok = true; |
| 1720 | |
| 1721 | bignum_init_float(&expr->const_val.data.x_bignum, x); |
| 1722 | |
| 1723 | if (expected_type) { |
| 1724 | num_lit_fits_in_other_type(g, node, expected_type); |
| 1725 | return expected_type; |
| 1726 | } else { |
| 1727 | return g->builtin_types.entry_num_lit_float; |
| 1728 | } |
| 1729 | } |
| 1730 | |
| 1731 | static TypeTableEntry *resolve_expr_const_val_as_bignum_op(CodeGen *g, AstNode *node, |
| 1732 | bool (*bignum_fn)(BigNum *, BigNum *, BigNum *), AstNode *op1, AstNode *op2, |
| 1733 | TypeTableEntry *resolved_type) |
| 1734 | { |
| 1735 | ConstExprValue *const_val = &get_resolved_expr(node)->const_val; |
| 1736 | ConstExprValue *op1_val = &get_resolved_expr(op1)->const_val; |
| 1737 | ConstExprValue *op2_val = &get_resolved_expr(op2)->const_val; |
| 1738 | |
| 1739 | const_val->ok = true; |
| 1740 | |
| 1741 | if (bignum_fn(&const_val->data.x_bignum, &op1_val->data.x_bignum, &op2_val->data.x_bignum)) { |
| 1742 | add_node_error(g, node, |
| 1743 | buf_sprintf("value cannot be represented in any integer type")); |
| 1744 | } else { |
| 1745 | num_lit_fits_in_other_type(g, node, resolved_type); |
| 1746 | } |
| 1747 | |
| 1748 | return resolved_type; |
| 1739 | 1749 | } |
| 1740 | 1750 | |
| 1751 | |
| 1741 | 1752 | static TypeTableEntry *analyze_symbol_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, |
| 1742 | 1753 | TypeTableEntry *expected_type, AstNode *node) |
| 1743 | 1754 | { |
| ... | ... | @@ -1918,60 +1929,6 @@ static bool eval_bool_bin_op_bool(bool a, BinOpType bin_op, bool b) { |
| 1918 | 1929 | } |
| 1919 | 1930 | } |
| 1920 | 1931 | |
| 1921 | | static bool eval_bool_bin_op_signed(int64_t a, BinOpType bin_op, int64_t b) { |
| 1922 | | if (bin_op == BinOpTypeCmpEq) { |
| 1923 | | return a == b; |
| 1924 | | } else if (bin_op == BinOpTypeCmpNotEq) { |
| 1925 | | return a != b; |
| 1926 | | } else if (bin_op == BinOpTypeCmpLessThan) { |
| 1927 | | return a < b; |
| 1928 | | } else if (bin_op == BinOpTypeCmpGreaterThan) { |
| 1929 | | return a > b; |
| 1930 | | } else if (bin_op == BinOpTypeCmpLessOrEq) { |
| 1931 | | return a <= b; |
| 1932 | | } else if (bin_op == BinOpTypeCmpGreaterOrEq) { |
| 1933 | | return a >= b; |
| 1934 | | } else { |
| 1935 | | zig_unreachable(); |
| 1936 | | } |
| 1937 | | } |
| 1938 | | |
| 1939 | | static bool eval_bool_bin_op_unsigned(uint64_t a, BinOpType bin_op, uint64_t b) { |
| 1940 | | if (bin_op == BinOpTypeCmpEq) { |
| 1941 | | return a == b; |
| 1942 | | } else if (bin_op == BinOpTypeCmpNotEq) { |
| 1943 | | return a != b; |
| 1944 | | } else if (bin_op == BinOpTypeCmpLessThan) { |
| 1945 | | return a < b; |
| 1946 | | } else if (bin_op == BinOpTypeCmpGreaterThan) { |
| 1947 | | return a > b; |
| 1948 | | } else if (bin_op == BinOpTypeCmpLessOrEq) { |
| 1949 | | return a <= b; |
| 1950 | | } else if (bin_op == BinOpTypeCmpGreaterOrEq) { |
| 1951 | | return a >= b; |
| 1952 | | } else { |
| 1953 | | zig_unreachable(); |
| 1954 | | } |
| 1955 | | } |
| 1956 | | |
| 1957 | | static bool eval_bool_bin_op_float(double a, BinOpType bin_op, double b) { |
| 1958 | | if (bin_op == BinOpTypeCmpEq) { |
| 1959 | | return a == b; |
| 1960 | | } else if (bin_op == BinOpTypeCmpNotEq) { |
| 1961 | | return a != b; |
| 1962 | | } else if (bin_op == BinOpTypeCmpLessThan) { |
| 1963 | | return a < b; |
| 1964 | | } else if (bin_op == BinOpTypeCmpGreaterThan) { |
| 1965 | | return a > b; |
| 1966 | | } else if (bin_op == BinOpTypeCmpLessOrEq) { |
| 1967 | | return a <= b; |
| 1968 | | } else if (bin_op == BinOpTypeCmpGreaterOrEq) { |
| 1969 | | return a >= b; |
| 1970 | | } else { |
| 1971 | | zig_unreachable(); |
| 1972 | | } |
| 1973 | | } |
| 1974 | | |
| 1975 | 1932 | static TypeTableEntry *analyze_bool_bin_op_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, |
| 1976 | 1933 | AstNode *node) |
| 1977 | 1934 | { |
| ... | ... | @@ -1983,8 +1940,11 @@ static TypeTableEntry *analyze_bool_bin_op_expr(CodeGen *g, ImportTableEntry *im |
| 1983 | 1940 | TypeTableEntry *op1_type = analyze_expression(g, import, context, nullptr, op1); |
| 1984 | 1941 | TypeTableEntry *op2_type = analyze_expression(g, import, context, nullptr, op2); |
| 1985 | 1942 | |
| 1943 | AstNode *op_nodes[] = {op1, op2}; |
| 1944 | TypeTableEntry *op_types[] = {op1_type, op2_type}; |
| 1945 | |
| 1986 | 1946 | TypeTableEntry *resolved_type = resolve_peer_type_compatibility(g, context, node, |
| 1987 | | op1, op2, op1_type, op2_type); |
| 1947 | op_nodes, op_types, 2); |
| 1988 | 1948 | |
| 1989 | 1949 | if (resolved_type->id == TypeTableEntryIdInvalid) { |
| 1990 | 1950 | return g->builtin_types.entry_invalid; |
| ... | ... | @@ -1997,20 +1957,30 @@ static TypeTableEntry *analyze_bool_bin_op_expr(CodeGen *g, ImportTableEntry *im |
| 1997 | 1957 | } |
| 1998 | 1958 | |
| 1999 | 1959 | bool answer; |
| 2000 | | if (resolved_type->id == TypeTableEntryIdInt) { |
| 2001 | | if (op1_type->data.integral.is_signed && |
| 2002 | | op2_type->data.integral.is_signed) |
| 2003 | | { |
| 2004 | | answer = eval_bool_bin_op_signed(op1_val->data.x_int, bin_op_type, op2_val->data.x_int); |
| 2005 | | } else if (!op1_type->data.integral.is_signed && |
| 2006 | | !op2_type->data.integral.is_signed) |
| 2007 | | { |
| 2008 | | answer = eval_bool_bin_op_unsigned(op1_val->data.x_uint, bin_op_type, op2_val->data.x_uint); |
| 1960 | if (resolved_type->id == TypeTableEntryIdNumLitFloat || |
| 1961 | resolved_type->id == TypeTableEntryIdNumLitInt || |
| 1962 | resolved_type->id == TypeTableEntryIdFloat || |
| 1963 | resolved_type->id == TypeTableEntryIdInt) |
| 1964 | { |
| 1965 | bool (*bignum_cmp)(BigNum *, BigNum *); |
| 1966 | if (bin_op_type == BinOpTypeCmpEq) { |
| 1967 | bignum_cmp = bignum_cmp_eq; |
| 1968 | } else if (bin_op_type == BinOpTypeCmpNotEq) { |
| 1969 | bignum_cmp = bignum_cmp_neq; |
| 1970 | } else if (bin_op_type == BinOpTypeCmpLessThan) { |
| 1971 | bignum_cmp = bignum_cmp_lt; |
| 1972 | } else if (bin_op_type == BinOpTypeCmpGreaterThan) { |
| 1973 | bignum_cmp = bignum_cmp_gt; |
| 1974 | } else if (bin_op_type == BinOpTypeCmpLessOrEq) { |
| 1975 | bignum_cmp = bignum_cmp_lte; |
| 1976 | } else if (bin_op_type == BinOpTypeCmpGreaterOrEq) { |
| 1977 | bignum_cmp = bignum_cmp_gte; |
| 2009 | 1978 | } else { |
| 2010 | 1979 | zig_unreachable(); |
| 2011 | 1980 | } |
| 2012 | | } else if (resolved_type->id == TypeTableEntryIdFloat) { |
| 2013 | | answer = eval_bool_bin_op_float(op1_val->data.x_float, bin_op_type, op2_val->data.x_float); |
| 1981 | |
| 1982 | answer = bignum_cmp(&op1_val->data.x_bignum, &op2_val->data.x_bignum); |
| 1983 | |
| 2014 | 1984 | } else if (resolved_type->id == TypeTableEntryIdEnum) { |
| 2015 | 1985 | ConstEnumValue *enum1 = &op1_val->data.x_enum; |
| 2016 | 1986 | ConstEnumValue *enum2 = &op2_val->data.x_enum; |
| ... | ... | @@ -2124,7 +2094,45 @@ static TypeTableEntry *analyze_bin_op_expr(CodeGen *g, ImportTableEntry *import, |
| 2124 | 2094 | TypeTableEntry *lhs_type = analyze_expression(g, import, context, expected_type, op1); |
| 2125 | 2095 | TypeTableEntry *rhs_type = analyze_expression(g, import, context, expected_type, op2); |
| 2126 | 2096 | |
| 2127 | | return resolve_peer_type_compatibility(g, context, node, op1, op2, lhs_type, rhs_type); |
| 2097 | AstNode *op_nodes[] = {op1, op2}; |
| 2098 | TypeTableEntry *op_types[] = {lhs_type, rhs_type}; |
| 2099 | |
| 2100 | TypeTableEntry *resolved_type = resolve_peer_type_compatibility(g, context, node, |
| 2101 | op_nodes, op_types, 2); |
| 2102 | |
| 2103 | if (resolved_type->id == TypeTableEntryIdInvalid) { |
| 2104 | return resolved_type; |
| 2105 | } |
| 2106 | |
| 2107 | ConstExprValue *op1_val = &get_resolved_expr(op1)->const_val; |
| 2108 | ConstExprValue *op2_val = &get_resolved_expr(op2)->const_val; |
| 2109 | if (!op1_val->ok || !op2_val->ok) { |
| 2110 | return resolved_type; |
| 2111 | } |
| 2112 | |
| 2113 | if (bin_op_type == BinOpTypeAdd) { |
| 2114 | return resolve_expr_const_val_as_bignum_op(g, node, bignum_add, op1, op2, resolved_type); |
| 2115 | } else if (bin_op_type == BinOpTypeSub) { |
| 2116 | return resolve_expr_const_val_as_bignum_op(g, node, bignum_sub, op1, op2, resolved_type); |
| 2117 | } else if (bin_op_type == BinOpTypeMult) { |
| 2118 | return resolve_expr_const_val_as_bignum_op(g, node, bignum_mul, op1, op2, resolved_type); |
| 2119 | } else if (bin_op_type == BinOpTypeDiv) { |
| 2120 | return resolve_expr_const_val_as_bignum_op(g, node, bignum_div, op1, op2, resolved_type); |
| 2121 | } else if (bin_op_type == BinOpTypeMod) { |
| 2122 | return resolve_expr_const_val_as_bignum_op(g, node, bignum_mod, op1, op2, resolved_type); |
| 2123 | } else if (bin_op_type == BinOpTypeBinOr) { |
| 2124 | return resolve_expr_const_val_as_bignum_op(g, node, bignum_or, op1, op2, resolved_type); |
| 2125 | } else if (bin_op_type == BinOpTypeBinAnd) { |
| 2126 | return resolve_expr_const_val_as_bignum_op(g, node, bignum_and, op1, op2, resolved_type); |
| 2127 | } else if (bin_op_type == BinOpTypeBinXor) { |
| 2128 | return resolve_expr_const_val_as_bignum_op(g, node, bignum_xor, op1, op2, resolved_type); |
| 2129 | } else if (bin_op_type == BinOpTypeBitShiftLeft) { |
| 2130 | return resolve_expr_const_val_as_bignum_op(g, node, bignum_shl, op1, op2, resolved_type); |
| 2131 | } else if (bin_op_type == BinOpTypeBitShiftRight) { |
| 2132 | return resolve_expr_const_val_as_bignum_op(g, node, bignum_shr, op1, op2, resolved_type); |
| 2133 | } else { |
| 2134 | zig_unreachable(); |
| 2135 | } |
| 2128 | 2136 | } |
| 2129 | 2137 | case BinOpTypeUnwrapMaybe: |
| 2130 | 2138 | { |
| ... | ... | @@ -2197,6 +2205,8 @@ static VariableTableEntry *analyze_variable_declaration_raw(CodeGen *g, ImportTa |
| 2197 | 2205 | AstNodeVariableDeclaration *variable_declaration, |
| 2198 | 2206 | bool expr_is_maybe) |
| 2199 | 2207 | { |
| 2208 | bool is_const = variable_declaration->is_const; |
| 2209 | |
| 2200 | 2210 | TypeTableEntry *explicit_type = nullptr; |
| 2201 | 2211 | if (variable_declaration->type != nullptr) { |
| 2202 | 2212 | explicit_type = analyze_type_expr(g, import, context, variable_declaration->type); |
| ... | ... | @@ -2223,19 +2233,19 @@ static VariableTableEntry *analyze_variable_declaration_raw(CodeGen *g, ImportTa |
| 2223 | 2233 | add_node_error(g, source_node, |
| 2224 | 2234 | buf_sprintf("variable initialization is unreachable")); |
| 2225 | 2235 | implicit_type = g->builtin_types.entry_invalid; |
| 2226 | | } else if (implicit_type->id == TypeTableEntryIdNumberLiteral) { |
| 2227 | | add_node_error(g, source_node, |
| 2228 | | buf_sprintf("unable to infer variable type")); |
| 2229 | | implicit_type = g->builtin_types.entry_invalid; |
| 2230 | | } else if (implicit_type->id == TypeTableEntryIdMetaType && |
| 2231 | | !variable_declaration->is_const) |
| 2236 | } else if (!is_const && |
| 2237 | (implicit_type->id == TypeTableEntryIdNumLitFloat || |
| 2238 | implicit_type->id == TypeTableEntryIdNumLitInt)) |
| 2232 | 2239 | { |
| 2240 | add_node_error(g, source_node, buf_sprintf("unable to infer variable type")); |
| 2241 | implicit_type = g->builtin_types.entry_invalid; |
| 2242 | } else if (implicit_type->id == TypeTableEntryIdMetaType && !is_const) { |
| 2233 | 2243 | add_node_error(g, source_node, buf_sprintf("variable of type 'type' must be constant")); |
| 2234 | 2244 | implicit_type = g->builtin_types.entry_invalid; |
| 2235 | 2245 | } |
| 2236 | 2246 | } |
| 2237 | 2247 | |
| 2238 | | if (implicit_type == nullptr && variable_declaration->is_const) { |
| 2248 | if (implicit_type == nullptr && is_const) { |
| 2239 | 2249 | add_node_error(g, source_node, buf_sprintf("const variable missing initialization")); |
| 2240 | 2250 | implicit_type = g->builtin_types.entry_invalid; |
| 2241 | 2251 | } |
| ... | ... | @@ -2244,7 +2254,7 @@ static VariableTableEntry *analyze_variable_declaration_raw(CodeGen *g, ImportTa |
| 2244 | 2254 | assert(type != nullptr); // should have been caught by the parser |
| 2245 | 2255 | |
| 2246 | 2256 | VariableTableEntry *var = add_local_var(g, source_node, context, |
| 2247 | | &variable_declaration->symbol, type, variable_declaration->is_const); |
| 2257 | &variable_declaration->symbol, type, is_const); |
| 2248 | 2258 | |
| 2249 | 2259 | |
| 2250 | 2260 | bool is_pub = (variable_declaration->visib_mod != VisibModPrivate); |
| ... | ... | @@ -2300,28 +2310,15 @@ static TypeTableEntry *analyze_number_literal_expr(CodeGen *g, ImportTableEntry |
| 2300 | 2310 | return g->builtin_types.entry_invalid; |
| 2301 | 2311 | } |
| 2302 | 2312 | |
| 2303 | | ConstExprValue *const_val = &get_resolved_expr(node)->const_val; |
| 2304 | | const_val->ok = true; |
| 2305 | | if (is_num_lit_unsigned(node->data.number_literal.kind)) { |
| 2306 | | const_val->data.x_uint = node->data.number_literal.data.x_uint; |
| 2307 | | } else if (is_num_lit_float(node->data.number_literal.kind)) { |
| 2308 | | const_val->data.x_float = node->data.number_literal.data.x_float; |
| 2313 | if (node->data.number_literal.kind == NumLitUInt) { |
| 2314 | return resolve_expr_const_val_as_unsigned_num_lit(g, node, |
| 2315 | expected_type, node->data.number_literal.data.x_uint); |
| 2316 | } else if (node->data.number_literal.kind == NumLitFloat) { |
| 2317 | return resolve_expr_const_val_as_float_num_lit(g, node, |
| 2318 | expected_type, node->data.number_literal.data.x_float); |
| 2309 | 2319 | } else { |
| 2310 | 2320 | zig_unreachable(); |
| 2311 | 2321 | } |
| 2312 | | |
| 2313 | | TypeTableEntry *num_lit_type = g->num_lit_types[node->data.number_literal.kind]; |
| 2314 | | if (expected_type) { |
| 2315 | | NumLitCodeGen *codegen_num_lit = get_resolved_num_lit(node); |
| 2316 | | assert(!codegen_num_lit->resolved_type); |
| 2317 | | TypeTableEntry *after_implicit_cast_resolved_type = |
| 2318 | | resolve_type_compatibility(g, block_context, node, expected_type, num_lit_type); |
| 2319 | | assert(codegen_num_lit->resolved_type || |
| 2320 | | after_implicit_cast_resolved_type->id == TypeTableEntryIdInvalid); |
| 2321 | | return after_implicit_cast_resolved_type; |
| 2322 | | } else { |
| 2323 | | return num_lit_type; |
| 2324 | | } |
| 2325 | 2322 | } |
| 2326 | 2323 | |
| 2327 | 2324 | static TypeTableEntry *analyze_error_literal_expr(CodeGen *g, ImportTableEntry *import, |
| ... | ... | @@ -2353,8 +2350,15 @@ static TypeTableEntry *analyze_array_type(CodeGen *g, ImportTableEntry *import, |
| 2353 | 2350 | |
| 2354 | 2351 | ConstExprValue *const_val = &get_resolved_expr(size_node)->const_val; |
| 2355 | 2352 | if (const_val->ok) { |
| 2356 | | return resolve_expr_const_val_as_type(g, node, |
| 2357 | | get_array_type(g, child_type, const_val->data.x_uint)); |
| 2353 | if (const_val->data.x_bignum.is_negative) { |
| 2354 | add_node_error(g, size_node, |
| 2355 | buf_sprintf("array size %s is negative", |
| 2356 | buf_ptr(bignum_to_buf(&const_val->data.x_bignum)))); |
| 2357 | return g->builtin_types.entry_invalid; |
| 2358 | } else { |
| 2359 | return resolve_expr_const_val_as_type(g, node, |
| 2360 | get_array_type(g, child_type, const_val->data.x_bignum.data.x_uint)); |
| 2361 | } |
| 2358 | 2362 | } else { |
| 2359 | 2363 | return resolve_expr_const_val_as_type(g, node, |
| 2360 | 2364 | get_unknown_size_array_type(g, child_type, node->data.array_type.is_const)); |
| ... | ... | @@ -2493,9 +2497,9 @@ static TypeTableEntry *analyze_if_then_else(CodeGen *g, ImportTableEntry *import |
| 2493 | 2497 | if (expected_type) { |
| 2494 | 2498 | return (then_type->id == TypeTableEntryIdUnreachable) ? else_type : then_type; |
| 2495 | 2499 | } else { |
| 2496 | | return resolve_peer_type_compatibility(g, context, parent_node, |
| 2497 | | then_block, else_node, |
| 2498 | | then_type, else_type); |
| 2500 | AstNode *op_nodes[] = {then_block, else_node}; |
| 2501 | TypeTableEntry *op_types[] = {then_type, else_type}; |
| 2502 | return resolve_peer_type_compatibility(g, context, parent_node, op_nodes, op_types, 2); |
| 2499 | 2503 | } |
| 2500 | 2504 | } |
| 2501 | 2505 | |
| ... | ... | @@ -2535,10 +2539,60 @@ static TypeTableEntry *analyze_min_max_value(CodeGen *g, ImportTableEntry *impor |
| 2535 | 2539 | if (type_entry->id == TypeTableEntryIdInvalid) { |
| 2536 | 2540 | return g->builtin_types.entry_invalid; |
| 2537 | 2541 | } else if (type_entry->id == TypeTableEntryIdInt) { |
| 2538 | | // TODO const expr eval for min/max int |
| 2542 | ConstExprValue *const_val = &get_resolved_expr(node)->const_val; |
| 2543 | const_val->ok = true; |
| 2544 | if (is_max) { |
| 2545 | if (type_entry->data.integral.is_signed) { |
| 2546 | int64_t val; |
| 2547 | if (type_entry->size_in_bits == 64) { |
| 2548 | val = INT64_MAX; |
| 2549 | } else if (type_entry->size_in_bits == 32) { |
| 2550 | val = INT32_MAX; |
| 2551 | } else if (type_entry->size_in_bits == 16) { |
| 2552 | val = INT16_MAX; |
| 2553 | } else if (type_entry->size_in_bits == 8) { |
| 2554 | val = INT8_MAX; |
| 2555 | } else { |
| 2556 | zig_unreachable(); |
| 2557 | } |
| 2558 | bignum_init_signed(&const_val->data.x_bignum, val); |
| 2559 | } else { |
| 2560 | uint64_t val; |
| 2561 | if (type_entry->size_in_bits == 64) { |
| 2562 | val = UINT64_MAX; |
| 2563 | } else if (type_entry->size_in_bits == 32) { |
| 2564 | val = UINT32_MAX; |
| 2565 | } else if (type_entry->size_in_bits == 16) { |
| 2566 | val = UINT16_MAX; |
| 2567 | } else if (type_entry->size_in_bits == 8) { |
| 2568 | val = UINT8_MAX; |
| 2569 | } else { |
| 2570 | zig_unreachable(); |
| 2571 | } |
| 2572 | bignum_init_unsigned(&const_val->data.x_bignum, val); |
| 2573 | } |
| 2574 | } else { |
| 2575 | if (type_entry->data.integral.is_signed) { |
| 2576 | int64_t val; |
| 2577 | if (type_entry->size_in_bits == 64) { |
| 2578 | val = INT64_MIN; |
| 2579 | } else if (type_entry->size_in_bits == 32) { |
| 2580 | val = INT32_MIN; |
| 2581 | } else if (type_entry->size_in_bits == 16) { |
| 2582 | val = INT16_MIN; |
| 2583 | } else if (type_entry->size_in_bits == 8) { |
| 2584 | val = INT8_MIN; |
| 2585 | } else { |
| 2586 | zig_unreachable(); |
| 2587 | } |
| 2588 | bignum_init_signed(&const_val->data.x_bignum, val); |
| 2589 | } else { |
| 2590 | bignum_init_unsigned(&const_val->data.x_bignum, 0); |
| 2591 | } |
| 2592 | } |
| 2539 | 2593 | return type_entry; |
| 2540 | 2594 | } else if (type_entry->id == TypeTableEntryIdFloat) { |
| 2541 | | // TODO const expr eval for min/max float |
| 2595 | zig_panic("TODO analyze_min_max_value float"); |
| 2542 | 2596 | return type_entry; |
| 2543 | 2597 | } else if (type_entry->id == TypeTableEntryIdBool) { |
| 2544 | 2598 | return resolve_expr_const_val_as_bool(g, node, is_max); |
| ... | ... | @@ -2559,10 +2613,9 @@ static void eval_const_expr_implicit_cast(CodeGen *g, ImportTableEntry *import, |
| 2559 | 2613 | case CastOpPointerReinterpret: |
| 2560 | 2614 | { |
| 2561 | 2615 | ConstExprValue *other_val = &get_resolved_expr(expr_node)->const_val; |
| 2562 | | ConstExprValue *const_val = &get_resolved_expr(node)->const_val; |
| 2563 | | if (other_val != const_val) { |
| 2564 | | *const_val = *other_val; |
| 2565 | | } |
| 2616 | ConstExprValue *const_val = &cast->const_val; |
| 2617 | assert(const_val != other_val); |
| 2618 | *const_val = *other_val; |
| 2566 | 2619 | break; |
| 2567 | 2620 | } |
| 2568 | 2621 | case CastOpToUnknownSizeArray: |
| ... | ... | @@ -2571,14 +2624,11 @@ static void eval_const_expr_implicit_cast(CodeGen *g, ImportTableEntry *import, |
| 2571 | 2624 | case CastOpMaybeWrap: |
| 2572 | 2625 | { |
| 2573 | 2626 | ConstExprValue *other_val = &get_resolved_expr(expr_node)->const_val; |
| 2574 | | ConstExprValue *const_val = &get_resolved_expr(node)->const_val; |
| 2627 | ConstExprValue *const_val = &cast->const_val; |
| 2575 | 2628 | if (!other_val->ok) { |
| 2576 | 2629 | break; |
| 2577 | | } else if (const_val == other_val) { |
| 2578 | | ConstExprValue *new_val = allocate<ConstExprValue>(1); |
| 2579 | | memcpy(new_val, other_val, sizeof(ConstExprValue)); |
| 2580 | | other_val = new_val; |
| 2581 | 2630 | } |
| 2631 | assert(const_val != other_val); |
| 2582 | 2632 | |
| 2583 | 2633 | const_val->data.x_maybe = other_val; |
| 2584 | 2634 | const_val->ok = true; |
| ... | ... | @@ -2635,12 +2685,10 @@ static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, B |
| 2635 | 2685 | context->cast_expr_alloca_list.append(cast); |
| 2636 | 2686 | eval_const_expr_implicit_cast(g, import, context, node, cast, expr_node); |
| 2637 | 2687 | return wanted_type; |
| 2638 | | } else if (actual_type->id == TypeTableEntryIdNumberLiteral && |
| 2639 | | num_lit_fits_in_other_type(g, actual_type, wanted_type)) |
| 2688 | } else if (actual_type->id == TypeTableEntryIdNumLitFloat || |
| 2689 | actual_type->id == TypeTableEntryIdNumLitInt) |
| 2640 | 2690 | { |
| 2641 | | NumLitCodeGen *codegen_num_lit = get_resolved_num_lit(expr_node); |
| 2642 | | assert(!codegen_num_lit->resolved_type); |
| 2643 | | codegen_num_lit->resolved_type = wanted_type; |
| 2691 | num_lit_fits_in_other_type(g, expr_node, wanted_type); |
| 2644 | 2692 | cast->op = CastOpNothing; |
| 2645 | 2693 | eval_const_expr_implicit_cast(g, import, context, node, cast, expr_node); |
| 2646 | 2694 | return wanted_type; |
| ... | ... | @@ -2998,7 +3046,7 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo |
| 2998 | 3046 | return g->builtin_types.entry_bool; |
| 2999 | 3047 | } |
| 3000 | 3048 | |
| 3001 | | bool answer = target_const_val->data.x_bool; |
| 3049 | bool answer = !target_const_val->data.x_bool; |
| 3002 | 3050 | return resolve_expr_const_val_as_bool(g, node, answer); |
| 3003 | 3051 | } |
| 3004 | 3052 | case PrefixOpBinNot: |
| ... | ... | @@ -3008,8 +3056,7 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo |
| 3008 | 3056 | if (expr_type->id == TypeTableEntryIdInvalid) { |
| 3009 | 3057 | return expr_type; |
| 3010 | 3058 | } else if (expr_type->id == TypeTableEntryIdInt || |
| 3011 | | (expr_type->id == TypeTableEntryIdNumberLiteral && |
| 3012 | | !is_num_lit_float(expr_type->data.num_lit.kind))) |
| 3059 | expr_type->id == TypeTableEntryIdNumLitInt) |
| 3013 | 3060 | { |
| 3014 | 3061 | return expr_type; |
| 3015 | 3062 | } else { |
| ... | ... | @@ -3017,6 +3064,7 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo |
| 3017 | 3064 | buf_ptr(&expr_type->name))); |
| 3018 | 3065 | return g->builtin_types.entry_invalid; |
| 3019 | 3066 | } |
| 3067 | // TODO const expr eval |
| 3020 | 3068 | } |
| 3021 | 3069 | case PrefixOpNegation: |
| 3022 | 3070 | { |
| ... | ... | @@ -3030,13 +3078,16 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo |
| 3030 | 3078 | return expr_type; |
| 3031 | 3079 | } else if (expr_type->id == TypeTableEntryIdFloat) { |
| 3032 | 3080 | return expr_type; |
| 3033 | | } else if (expr_type->id == TypeTableEntryIdNumberLiteral) { |
| 3081 | } else if (expr_type->id == TypeTableEntryIdNumLitInt) { |
| 3082 | return expr_type; |
| 3083 | } else if (expr_type->id == TypeTableEntryIdNumLitFloat) { |
| 3034 | 3084 | return expr_type; |
| 3035 | 3085 | } else { |
| 3036 | 3086 | add_node_error(g, node, buf_sprintf("invalid negation type: '%s'", |
| 3037 | 3087 | buf_ptr(&expr_type->name))); |
| 3038 | 3088 | return g->builtin_types.entry_invalid; |
| 3039 | 3089 | } |
| 3090 | // TODO const expr eval |
| 3040 | 3091 | } |
| 3041 | 3092 | case PrefixOpAddressOf: |
| 3042 | 3093 | case PrefixOpConstAddressOf: |
| ... | ... | @@ -4129,59 +4180,6 @@ Expr *get_resolved_expr(AstNode *node) { |
| 4129 | 4180 | zig_unreachable(); |
| 4130 | 4181 | } |
| 4131 | 4182 | |
| 4132 | | NumLitCodeGen *get_resolved_num_lit(AstNode *node) { |
| 4133 | | switch (node->type) { |
| 4134 | | case NodeTypeNumberLiteral: |
| 4135 | | return &node->data.number_literal.codegen; |
| 4136 | | case NodeTypeErrorLiteral: |
| 4137 | | return &node->data.error_literal.codegen; |
| 4138 | | case NodeTypeFnCallExpr: |
| 4139 | | return &node->data.fn_call_expr.resolved_num_lit; |
| 4140 | | case NodeTypeReturnExpr: |
| 4141 | | case NodeTypeBinOpExpr: |
| 4142 | | case NodeTypePrefixOpExpr: |
| 4143 | | case NodeTypeArrayAccessExpr: |
| 4144 | | case NodeTypeSliceExpr: |
| 4145 | | case NodeTypeFieldAccessExpr: |
| 4146 | | case NodeTypeIfBoolExpr: |
| 4147 | | case NodeTypeIfVarExpr: |
| 4148 | | case NodeTypeWhileExpr: |
| 4149 | | case NodeTypeForExpr: |
| 4150 | | case NodeTypeSwitchExpr: |
| 4151 | | case NodeTypeSwitchProng: |
| 4152 | | case NodeTypeSwitchRange: |
| 4153 | | case NodeTypeAsmExpr: |
| 4154 | | case NodeTypeContainerInitExpr: |
| 4155 | | case NodeTypeRoot: |
| 4156 | | case NodeTypeRootExportDecl: |
| 4157 | | case NodeTypeFnProto: |
| 4158 | | case NodeTypeFnDef: |
| 4159 | | case NodeTypeFnDecl: |
| 4160 | | case NodeTypeParamDecl: |
| 4161 | | case NodeTypeBlock: |
| 4162 | | case NodeTypeExternBlock: |
| 4163 | | case NodeTypeDirective: |
| 4164 | | case NodeTypeVariableDeclaration: |
| 4165 | | case NodeTypeStringLiteral: |
| 4166 | | case NodeTypeCharLiteral: |
| 4167 | | case NodeTypeSymbol: |
| 4168 | | case NodeTypeUse: |
| 4169 | | case NodeTypeBoolLiteral: |
| 4170 | | case NodeTypeNullLiteral: |
| 4171 | | case NodeTypeLabel: |
| 4172 | | case NodeTypeGoto: |
| 4173 | | case NodeTypeBreak: |
| 4174 | | case NodeTypeContinue: |
| 4175 | | case NodeTypeStructDecl: |
| 4176 | | case NodeTypeStructField: |
| 4177 | | case NodeTypeStructValueField: |
| 4178 | | case NodeTypeArrayType: |
| 4179 | | case NodeTypeErrorValueDecl: |
| 4180 | | zig_unreachable(); |
| 4181 | | } |
| 4182 | | zig_unreachable(); |
| 4183 | | } |
| 4184 | | |
| 4185 | 4183 | TopLevelDecl *get_resolved_top_level_decl(AstNode *node) { |
| 4186 | 4184 | switch (node->type) { |
| 4187 | 4185 | case NodeTypeVariableDeclaration: |