| ... | ... | @@ -661,6 +661,8 @@ static bool num_lit_fits_in_other_type(CodeGen *g, TypeTableEntry *literal_type, |
| 661 | 661 | } else { |
| 662 | 662 | return false; |
| 663 | 663 | } |
| 664 | case TypeTableEntryIdMaybe: |
| 665 | return num_lit_fits_in_other_type(g, literal_type, other_type->data.maybe.child_type); |
| 664 | 666 | } |
| 665 | 667 | zig_unreachable(); |
| 666 | 668 | } |
| ... | ... | @@ -1220,11 +1222,11 @@ static TypeTableEntry *analyze_bin_op_expr(CodeGen *g, ImportTableEntry *import, |
| 1220 | 1222 | zig_unreachable(); |
| 1221 | 1223 | } |
| 1222 | 1224 | |
| 1223 | | static VariableTableEntry *analyze_variable_declaration(CodeGen *g, ImportTableEntry *import, |
| 1224 | | BlockContext *context, TypeTableEntry *expected_type, AstNode *node) |
| 1225 | static VariableTableEntry *analyze_variable_declaration_raw(CodeGen *g, ImportTableEntry *import, |
| 1226 | BlockContext *context, AstNode *source_node, |
| 1227 | AstNodeVariableDeclaration *variable_declaration, |
| 1228 | bool expr_is_maybe) |
| 1225 | 1229 | { |
| 1226 | | AstNodeVariableDeclaration *variable_declaration = &node->data.variable_declaration; |
| 1227 | | |
| 1228 | 1230 | TypeTableEntry *explicit_type = nullptr; |
| 1229 | 1231 | if (variable_declaration->type != nullptr) { |
| 1230 | 1232 | explicit_type = resolve_type(g, variable_declaration->type); |
| ... | ... | @@ -1238,19 +1240,28 @@ static VariableTableEntry *analyze_variable_declaration(CodeGen *g, ImportTableE |
| 1238 | 1240 | TypeTableEntry *implicit_type = nullptr; |
| 1239 | 1241 | if (variable_declaration->expr != nullptr) { |
| 1240 | 1242 | implicit_type = analyze_expression(g, import, context, explicit_type, variable_declaration->expr); |
| 1241 | | if (implicit_type->id == TypeTableEntryIdUnreachable) { |
| 1242 | | add_node_error(g, node, |
| 1243 | if (implicit_type->id == TypeTableEntryIdInvalid) { |
| 1244 | // ignore the poison value |
| 1245 | } else if (expr_is_maybe) { |
| 1246 | if (implicit_type->id == TypeTableEntryIdMaybe) { |
| 1247 | implicit_type = implicit_type->data.maybe.child_type; |
| 1248 | } else { |
| 1249 | add_node_error(g, source_node, buf_sprintf("expected maybe type")); |
| 1250 | implicit_type = g->builtin_types.entry_invalid; |
| 1251 | } |
| 1252 | } else if (implicit_type->id == TypeTableEntryIdUnreachable) { |
| 1253 | add_node_error(g, source_node, |
| 1243 | 1254 | buf_sprintf("variable initialization is unreachable")); |
| 1244 | 1255 | implicit_type = g->builtin_types.entry_invalid; |
| 1245 | 1256 | } else if (implicit_type->id == TypeTableEntryIdNumberLiteral) { |
| 1246 | | add_node_error(g, node, |
| 1257 | add_node_error(g, source_node, |
| 1247 | 1258 | buf_sprintf("unable to infer variable type")); |
| 1248 | 1259 | implicit_type = g->builtin_types.entry_invalid; |
| 1249 | 1260 | } |
| 1250 | 1261 | } |
| 1251 | 1262 | |
| 1252 | 1263 | if (implicit_type == nullptr && variable_declaration->is_const) { |
| 1253 | | add_node_error(g, node, buf_sprintf("variables must have initial values or be declared 'mut'.")); |
| 1264 | add_node_error(g, source_node, buf_sprintf("variables must have initial values or be declared 'mut'.")); |
| 1254 | 1265 | implicit_type = g->builtin_types.entry_invalid; |
| 1255 | 1266 | } |
| 1256 | 1267 | |
| ... | ... | @@ -1259,7 +1270,7 @@ static VariableTableEntry *analyze_variable_declaration(CodeGen *g, ImportTableE |
| 1259 | 1270 | |
| 1260 | 1271 | VariableTableEntry *existing_variable = find_local_variable(context, &variable_declaration->symbol); |
| 1261 | 1272 | if (existing_variable) { |
| 1262 | | add_node_error(g, node, |
| 1273 | add_node_error(g, source_node, |
| 1263 | 1274 | buf_sprintf("redeclaration of variable '%s'", buf_ptr(&variable_declaration->symbol))); |
| 1264 | 1275 | } else { |
| 1265 | 1276 | VariableTableEntry *variable_entry = allocate<VariableTableEntry>(1); |
| ... | ... | @@ -1267,13 +1278,20 @@ static VariableTableEntry *analyze_variable_declaration(CodeGen *g, ImportTableE |
| 1267 | 1278 | variable_entry->type = type; |
| 1268 | 1279 | variable_entry->is_const = variable_declaration->is_const; |
| 1269 | 1280 | variable_entry->is_ptr = true; |
| 1270 | | variable_entry->decl_node = node; |
| 1281 | variable_entry->decl_node = source_node; |
| 1271 | 1282 | context->variable_table.put(&variable_entry->name, variable_entry); |
| 1272 | 1283 | return variable_entry; |
| 1273 | 1284 | } |
| 1274 | 1285 | return nullptr; |
| 1275 | 1286 | } |
| 1276 | 1287 | |
| 1288 | static VariableTableEntry *analyze_variable_declaration(CodeGen *g, ImportTableEntry *import, |
| 1289 | BlockContext *context, TypeTableEntry *expected_type, AstNode *node) |
| 1290 | { |
| 1291 | AstNodeVariableDeclaration *variable_declaration = &node->data.variable_declaration; |
| 1292 | return analyze_variable_declaration_raw(g, import, context, node, variable_declaration, false); |
| 1293 | } |
| 1294 | |
| 1277 | 1295 | static TypeTableEntry *analyze_number_literal_expr(CodeGen *g, ImportTableEntry *import, |
| 1278 | 1296 | BlockContext *block_context, TypeTableEntry *expected_type, AstNode *node) |
| 1279 | 1297 | { |
| ... | ... | @@ -1397,37 +1415,51 @@ static TypeTableEntry *analyze_continue_expr(CodeGen *g, ImportTableEntry *impor |
| 1397 | 1415 | return g->builtin_types.entry_unreachable; |
| 1398 | 1416 | } |
| 1399 | 1417 | |
| 1400 | | static TypeTableEntry *analyze_if_bool_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, |
| 1401 | | TypeTableEntry *expected_type, AstNode *node) |
| 1418 | static TypeTableEntry *analyze_if_then_else(CodeGen *g, ImportTableEntry *import, BlockContext *context, |
| 1419 | TypeTableEntry *expected_type, AstNode *then_block, AstNode *else_node, AstNode *parent_node) |
| 1402 | 1420 | { |
| 1403 | | analyze_expression(g, import, context, g->builtin_types.entry_bool, node->data.if_bool_expr.condition); |
| 1404 | | |
| 1405 | | TypeTableEntry *then_type = analyze_expression(g, import, context, expected_type, |
| 1406 | | node->data.if_bool_expr.then_block); |
| 1421 | TypeTableEntry *then_type = analyze_expression(g, import, context, expected_type, then_block); |
| 1407 | 1422 | |
| 1408 | 1423 | TypeTableEntry *else_type; |
| 1409 | | if (node->data.if_bool_expr.else_node) { |
| 1410 | | else_type = analyze_expression(g, import, context, expected_type, node->data.if_bool_expr.else_node); |
| 1424 | if (else_node) { |
| 1425 | else_type = analyze_expression(g, import, context, expected_type, else_node); |
| 1411 | 1426 | } else { |
| 1412 | 1427 | else_type = g->builtin_types.entry_void; |
| 1413 | | else_type = resolve_type_compatibility(g, context, node, expected_type, else_type); |
| 1428 | else_type = resolve_type_compatibility(g, context, parent_node, expected_type, else_type); |
| 1414 | 1429 | } |
| 1415 | 1430 | |
| 1416 | 1431 | |
| 1417 | 1432 | if (expected_type) { |
| 1418 | 1433 | return (then_type->id == TypeTableEntryIdUnreachable) ? else_type : then_type; |
| 1419 | 1434 | } else { |
| 1420 | | return resolve_peer_type_compatibility(g, context, node, |
| 1421 | | node->data.if_bool_expr.then_block, node->data.if_bool_expr.else_node, |
| 1435 | return resolve_peer_type_compatibility(g, context, parent_node, |
| 1436 | then_block, else_node, |
| 1422 | 1437 | then_type, else_type); |
| 1423 | 1438 | } |
| 1424 | 1439 | } |
| 1425 | 1440 | |
| 1441 | static TypeTableEntry *analyze_if_bool_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, |
| 1442 | TypeTableEntry *expected_type, AstNode *node) |
| 1443 | { |
| 1444 | analyze_expression(g, import, context, g->builtin_types.entry_bool, node->data.if_bool_expr.condition); |
| 1445 | |
| 1446 | return analyze_if_then_else(g, import, context, expected_type, |
| 1447 | node->data.if_bool_expr.then_block, |
| 1448 | node->data.if_bool_expr.else_node, |
| 1449 | node); |
| 1450 | } |
| 1451 | |
| 1426 | 1452 | static TypeTableEntry *analyze_if_var_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, |
| 1427 | 1453 | TypeTableEntry *expected_type, AstNode *node) |
| 1428 | 1454 | { |
| 1429 | 1455 | assert(node->type == NodeTypeIfVarExpr); |
| 1430 | | zig_panic("TODO analyze_if_var_expr"); |
| 1456 | |
| 1457 | BlockContext *child_context = new_block_context(node, context); |
| 1458 | |
| 1459 | analyze_variable_declaration_raw(g, import, child_context, node, &node->data.if_var_expr.var_decl, true); |
| 1460 | |
| 1461 | return analyze_if_then_else(g, import, child_context, expected_type, |
| 1462 | node->data.if_var_expr.then_block, node->data.if_var_expr.else_node, node); |
| 1431 | 1463 | } |
| 1432 | 1464 | |
| 1433 | 1465 | static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, BlockContext *context, |