| ... | @@ -661,6 +661,8 @@ static bool num_lit_fits_in_other_type(CodeGen *g, TypeTableEntry *literal_type, | ... | @@ -661,6 +661,8 @@ static bool num_lit_fits_in_other_type(CodeGen *g, TypeTableEntry *literal_type, |
| 661 | } else { | 661 | } else { |
| 662 | return false; | 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 | zig_unreachable(); | 667 | zig_unreachable(); |
| 666 | } | 668 | } |
| ... | @@ -1220,11 +1222,11 @@ static TypeTableEntry *analyze_bin_op_expr(CodeGen *g, ImportTableEntry *import, | ... | @@ -1220,11 +1222,11 @@ static TypeTableEntry *analyze_bin_op_expr(CodeGen *g, ImportTableEntry *import, |
| 1220 | zig_unreachable(); | 1222 | zig_unreachable(); |
| 1221 | } | 1223 | } |
| 1222 | | 1224 | |
| 1223 | static VariableTableEntry *analyze_variable_declaration(CodeGen *g, ImportTableEntry *import, | 1225 | static VariableTableEntry *analyze_variable_declaration_raw(CodeGen *g, ImportTableEntry *import, |
| 1224 | BlockContext *context, TypeTableEntry *expected_type, AstNode *node) | 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 | TypeTableEntry *explicit_type = nullptr; | 1230 | TypeTableEntry *explicit_type = nullptr; |
| 1229 | if (variable_declaration->type != nullptr) { | 1231 | if (variable_declaration->type != nullptr) { |
| 1230 | explicit_type = resolve_type(g, variable_declaration->type); | 1232 | explicit_type = resolve_type(g, variable_declaration->type); |
| ... | @@ -1238,19 +1240,28 @@ static VariableTableEntry *analyze_variable_declaration(CodeGen *g, ImportTableE | ... | @@ -1238,19 +1240,28 @@ static VariableTableEntry *analyze_variable_declaration(CodeGen *g, ImportTableE |
| 1238 | TypeTableEntry *implicit_type = nullptr; | 1240 | TypeTableEntry *implicit_type = nullptr; |
| 1239 | if (variable_declaration->expr != nullptr) { | 1241 | if (variable_declaration->expr != nullptr) { |
| 1240 | implicit_type = analyze_expression(g, import, context, explicit_type, variable_declaration->expr); | 1242 | implicit_type = analyze_expression(g, import, context, explicit_type, variable_declaration->expr); |
| 1241 | if (implicit_type->id == TypeTableEntryIdUnreachable) { | 1243 | if (implicit_type->id == TypeTableEntryIdInvalid) { |
| 1242 | add_node_error(g, node, | 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 | buf_sprintf("variable initialization is unreachable")); | 1254 | buf_sprintf("variable initialization is unreachable")); |
| 1244 | implicit_type = g->builtin_types.entry_invalid; | 1255 | implicit_type = g->builtin_types.entry_invalid; |
| 1245 | } else if (implicit_type->id == TypeTableEntryIdNumberLiteral) { | 1256 | } else if (implicit_type->id == TypeTableEntryIdNumberLiteral) { |
| 1246 | add_node_error(g, node, | 1257 | add_node_error(g, source_node, |
| 1247 | buf_sprintf("unable to infer variable type")); | 1258 | buf_sprintf("unable to infer variable type")); |
| 1248 | implicit_type = g->builtin_types.entry_invalid; | 1259 | implicit_type = g->builtin_types.entry_invalid; |
| 1249 | } | 1260 | } |
| 1250 | } | 1261 | } |
| 1251 | | 1262 | |
| 1252 | if (implicit_type == nullptr && variable_declaration->is_const) { | 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 | implicit_type = g->builtin_types.entry_invalid; | 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,7 +1270,7 @@ static VariableTableEntry *analyze_variable_declaration(CodeGen *g, ImportTableE |
| 1259 | | 1270 | |
| 1260 | VariableTableEntry *existing_variable = find_local_variable(context, &variable_declaration->symbol); | 1271 | VariableTableEntry *existing_variable = find_local_variable(context, &variable_declaration->symbol); |
| 1261 | if (existing_variable) { | 1272 | if (existing_variable) { |
| 1262 | add_node_error(g, node, | 1273 | add_node_error(g, source_node, |
| 1263 | buf_sprintf("redeclaration of variable '%s'", buf_ptr(&variable_declaration->symbol))); | 1274 | buf_sprintf("redeclaration of variable '%s'", buf_ptr(&variable_declaration->symbol))); |
| 1264 | } else { | 1275 | } else { |
| 1265 | VariableTableEntry *variable_entry = allocate<VariableTableEntry>(1); | 1276 | VariableTableEntry *variable_entry = allocate<VariableTableEntry>(1); |
| ... | @@ -1267,13 +1278,20 @@ static VariableTableEntry *analyze_variable_declaration(CodeGen *g, ImportTableE | ... | @@ -1267,13 +1278,20 @@ static VariableTableEntry *analyze_variable_declaration(CodeGen *g, ImportTableE |
| 1267 | variable_entry->type = type; | 1278 | variable_entry->type = type; |
| 1268 | variable_entry->is_const = variable_declaration->is_const; | 1279 | variable_entry->is_const = variable_declaration->is_const; |
| 1269 | variable_entry->is_ptr = true; | 1280 | variable_entry->is_ptr = true; |
| 1270 | variable_entry->decl_node = node; | 1281 | variable_entry->decl_node = source_node; |
| 1271 | context->variable_table.put(&variable_entry->name, variable_entry); | 1282 | context->variable_table.put(&variable_entry->name, variable_entry); |
| 1272 | return variable_entry; | 1283 | return variable_entry; |
| 1273 | } | 1284 | } |
| 1274 | return nullptr; | 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 | static TypeTableEntry *analyze_number_literal_expr(CodeGen *g, ImportTableEntry *import, | 1295 | static TypeTableEntry *analyze_number_literal_expr(CodeGen *g, ImportTableEntry *import, |
| 1278 | BlockContext *block_context, TypeTableEntry *expected_type, AstNode *node) | 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,37 +1415,51 @@ static TypeTableEntry *analyze_continue_expr(CodeGen *g, ImportTableEntry *impor |
| 1397 | return g->builtin_types.entry_unreachable; | 1415 | return g->builtin_types.entry_unreachable; |
| 1398 | } | 1416 | } |
| 1399 | | 1417 | |
| 1400 | static TypeTableEntry *analyze_if_bool_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, | 1418 | static TypeTableEntry *analyze_if_then_else(CodeGen *g, ImportTableEntry *import, BlockContext *context, |
| 1401 | TypeTableEntry *expected_type, AstNode *node) | 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); | 1421 | TypeTableEntry *then_type = analyze_expression(g, import, context, expected_type, then_block); |
| 1404 | | | |
| 1405 | TypeTableEntry *then_type = analyze_expression(g, import, context, expected_type, | | |
| 1406 | node->data.if_bool_expr.then_block); | | |
| 1407 | | 1422 | |
| 1408 | TypeTableEntry *else_type; | 1423 | TypeTableEntry *else_type; |
| 1409 | if (node->data.if_bool_expr.else_node) { | 1424 | if (else_node) { |
| 1410 | else_type = analyze_expression(g, import, context, expected_type, node->data.if_bool_expr.else_node); | 1425 | else_type = analyze_expression(g, import, context, expected_type, else_node); |
| 1411 | } else { | 1426 | } else { |
| 1412 | else_type = g->builtin_types.entry_void; | 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 | if (expected_type) { | 1432 | if (expected_type) { |
| 1418 | return (then_type->id == TypeTableEntryIdUnreachable) ? else_type : then_type; | 1433 | return (then_type->id == TypeTableEntryIdUnreachable) ? else_type : then_type; |
| 1419 | } else { | 1434 | } else { |
| 1420 | return resolve_peer_type_compatibility(g, context, node, | 1435 | return resolve_peer_type_compatibility(g, context, parent_node, |
| 1421 | node->data.if_bool_expr.then_block, node->data.if_bool_expr.else_node, | 1436 | then_block, else_node, |
| 1422 | then_type, else_type); | 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 | static TypeTableEntry *analyze_if_var_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, | 1452 | static TypeTableEntry *analyze_if_var_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, |
| 1427 | TypeTableEntry *expected_type, AstNode *node) | 1453 | TypeTableEntry *expected_type, AstNode *node) |
| 1428 | { | 1454 | { |
| 1429 | assert(node->type == NodeTypeIfVarExpr); | 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 | static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, BlockContext *context, | 1465 | static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, BlockContext *context, |