authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2015-12-26 15:43:40-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2015-12-26 15:43:40-07:00
log7ba99e9715c1fa3cd00fe6d9ac74b9a15eeac706
tree3ce60bcf77470440292beb7551ce0f0851e7a9a3
parent1f8e3871ee11c71b7965e8b9e97fa37a8e994d68

analyze if maybe var expressions


3 files changed, 61 insertions(+), 23 deletions(-)

example/guess_number/main.zig+1-1
...@@ -12,7 +12,7 @@ fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {...@@ -12,7 +12,7 @@ fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
12 const answer = rand_int(&rand_state, 0, 100) + 1;12 const answer = rand_int(&rand_state, 0, 100) + 1;
1313
14 while true {14 while true {
15 line = readline("\nGuess a number between 1 and 100: ");15 const line = readline("\nGuess a number between 1 and 100: ");
1616
17 if const guess ?= parse_number(line) {17 if const guess ?= parse_number(line) {
18 if (guess > answer) {18 if (guess > answer) {
src/analyze.cpp+54-22
...@@ -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}
12221224
1223static VariableTableEntry *analyze_variable_declaration(CodeGen *g, ImportTableEntry *import,1225static 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 }
12511262
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 }
12561267
...@@ -1259,7 +1270,7 @@ static VariableTableEntry *analyze_variable_declaration(CodeGen *g, ImportTableE...@@ -1259,7 +1270,7 @@ static VariableTableEntry *analyze_variable_declaration(CodeGen *g, ImportTableE
12591270
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}
12761287
1288static 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
1277static TypeTableEntry *analyze_number_literal_expr(CodeGen *g, ImportTableEntry *import,1295static 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}
13991417
1400static TypeTableEntry *analyze_if_bool_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,1418static 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);
14071422
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 }
14151430
14161431
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}
14251440
1441static 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
1426static TypeTableEntry *analyze_if_var_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,1452static 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}
14321464
1433static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, BlockContext *context,1465static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, BlockContext *context,
src/analyze.hpp+6
...@@ -55,6 +55,10 @@ struct TypeTableEntryNumLit {...@@ -55,6 +55,10 @@ struct TypeTableEntryNumLit {
55 NumLit kind;55 NumLit kind;
56};56};
5757
58struct TypeTableEntryMaybe {
59 TypeTableEntry *child_type;
60};
61
58enum TypeTableEntryId {62enum TypeTableEntryId {
59 TypeTableEntryIdInvalid,63 TypeTableEntryIdInvalid,
60 TypeTableEntryIdVoid,64 TypeTableEntryIdVoid,
...@@ -66,6 +70,7 @@ enum TypeTableEntryId {...@@ -66,6 +70,7 @@ enum TypeTableEntryId {
66 TypeTableEntryIdArray,70 TypeTableEntryIdArray,
67 TypeTableEntryIdStruct,71 TypeTableEntryIdStruct,
68 TypeTableEntryIdNumberLiteral,72 TypeTableEntryIdNumberLiteral,
73 TypeTableEntryIdMaybe,
69};74};
7075
71struct TypeTableEntry {76struct TypeTableEntry {
...@@ -84,6 +89,7 @@ struct TypeTableEntry {...@@ -84,6 +89,7 @@ struct TypeTableEntry {
84 TypeTableEntryArray array;89 TypeTableEntryArray array;
85 TypeTableEntryStruct structure;90 TypeTableEntryStruct structure;
86 TypeTableEntryNumLit num_lit;91 TypeTableEntryNumLit num_lit;
92 TypeTableEntryMaybe maybe;
87 } data;93 } data;
8894
89 // use these fields to make sure we don't duplicate type table entries for the same type95 // use these fields to make sure we don't duplicate type table entries for the same type