authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-02-05 23:20:34-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-02-05 23:20:34-07:00
log6a2ede5a6eb17d6b86e6636457710a3583376fa3
tree5d0968960e8c37e325de3f78d7c1cb86533bdd05
parent4339d555626197f4b8c9598b602f098b76488c2d

parsing code for defer and more

* disable goto and label support see #44 * refactor the way block contexts work

11 files changed, 344 insertions(+), 326 deletions(-)

doc/langref.md+3-1
...@@ -51,7 +51,7 @@ Expression = BlockExpression | NonBlockExpression...@@ -51,7 +51,7 @@ Expression = BlockExpression | NonBlockExpression
5151
52TypeExpr = PrefixOpExpression52TypeExpr = PrefixOpExpression
5353
54NonBlockExpression = ReturnExpression | AssignmentExpression54NonBlockExpression = ReturnExpression | AssignmentExpression | DeferExpression
5555
56AsmExpression = "asm" option("volatile") "(" "String" option(AsmOutput) ")"56AsmExpression = "asm" option("volatile") "(" "String" option(AsmOutput) ")"
5757
...@@ -91,6 +91,8 @@ BoolOrExpression = BoolAndExpression "||" BoolOrExpression | BoolAndExpression...@@ -91,6 +91,8 @@ BoolOrExpression = BoolAndExpression "||" BoolOrExpression | BoolAndExpression
9191
92ReturnExpression = option("%" | "?") "return" option(Expression)92ReturnExpression = option("%" | "?") "return" option(Expression)
9393
94DeferExpression = option("%" | "?") "defer" option(Expression)
95
94IfExpression = IfVarExpression | IfBoolExpression96IfExpression = IfVarExpression | IfBoolExpression
9597
96IfBoolExpression = "if" "(" Expression ")" Expression option(Else)98IfBoolExpression = "if" "(" Expression ")" Expression option(Else)
src/all_types.hpp+39-21
...@@ -24,7 +24,6 @@ struct TypeTableEntry;...@@ -24,7 +24,6 @@ struct TypeTableEntry;
24struct VariableTableEntry;24struct VariableTableEntry;
25struct ErrorTableEntry;25struct ErrorTableEntry;
26struct BuiltinFnEntry;26struct BuiltinFnEntry;
27struct LabelTableEntry;
28struct TypeStructField;27struct TypeStructField;
29struct CodeGen;28struct CodeGen;
30struct ConstExprValue;29struct ConstExprValue;
...@@ -118,6 +117,7 @@ enum NodeType {...@@ -118,6 +117,7 @@ enum NodeType {
118 NodeTypeBlock,117 NodeTypeBlock,
119 NodeTypeDirective,118 NodeTypeDirective,
120 NodeTypeReturnExpr,119 NodeTypeReturnExpr,
120 NodeTypeDeferExpr,
121 NodeTypeVariableDeclaration,121 NodeTypeVariableDeclaration,
122 NodeTypeTypeDecl,122 NodeTypeTypeDecl,
123 NodeTypeErrorValueDecl,123 NodeTypeErrorValueDecl,
...@@ -235,6 +235,16 @@ struct AstNodeReturnExpr {...@@ -235,6 +235,16 @@ struct AstNodeReturnExpr {
235 Expr resolved_expr;235 Expr resolved_expr;
236};236};
237237
238struct AstNodeDeferExpr {
239 ReturnKind kind;
240 AstNode *expr;
241
242 // populated by semantic analyzer:
243 Expr resolved_expr;
244 int index_in_block;
245 LLVMBasicBlockRef basic_block;
246};
247
238struct AstNodeVariableDeclaration {248struct AstNodeVariableDeclaration {
239 Buf symbol;249 Buf symbol;
240 bool is_const;250 bool is_const;
...@@ -477,7 +487,6 @@ struct AstNodeWhileExpr {...@@ -477,7 +487,6 @@ struct AstNodeWhileExpr {
477 bool contains_break;487 bool contains_break;
478 bool contains_continue;488 bool contains_continue;
479 Expr resolved_expr;489 Expr resolved_expr;
480 BlockContext *block_context;
481};490};
482491
483struct AstNodeForExpr {492struct AstNodeForExpr {
...@@ -522,7 +531,6 @@ struct AstNodeLabel {...@@ -522,7 +531,6 @@ struct AstNodeLabel {
522 Buf name;531 Buf name;
523532
524 // populated by semantic analyzer533 // populated by semantic analyzer
525 LabelTableEntry *label_entry;
526 Expr resolved_expr;534 Expr resolved_expr;
527};535};
528536
...@@ -530,7 +538,6 @@ struct AstNodeGoto {...@@ -530,7 +538,6 @@ struct AstNodeGoto {
530 Buf name;538 Buf name;
531539
532 // populated by semantic analyzer540 // populated by semantic analyzer
533 LabelTableEntry *label_entry;
534 Expr resolved_expr;541 Expr resolved_expr;
535};542};
536543
...@@ -732,6 +739,7 @@ struct AstNode {...@@ -732,6 +739,7 @@ struct AstNode {
732 AstNodeParamDecl param_decl;739 AstNodeParamDecl param_decl;
733 AstNodeBlock block;740 AstNodeBlock block;
734 AstNodeReturnExpr return_expr;741 AstNodeReturnExpr return_expr;
742 AstNodeDeferExpr defer_expr;
735 AstNodeVariableDeclaration variable_declaration;743 AstNodeVariableDeclaration variable_declaration;
736 AstNodeTypeDecl type_decl;744 AstNodeTypeDecl type_decl;
737 AstNodeErrorValueDecl error_value_decl;745 AstNodeErrorValueDecl error_value_decl;
...@@ -967,13 +975,8 @@ struct ImportTableEntry {...@@ -967,13 +975,8 @@ struct ImportTableEntry {
967975
968 // reminder: hash tables must be initialized before use976 // reminder: hash tables must be initialized before use
969 HashMap<Buf *, FnTableEntry *, buf_hash, buf_eql_buf> fn_table;977 HashMap<Buf *, FnTableEntry *, buf_hash, buf_eql_buf> fn_table;
970};978 HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> type_table;
971979 HashMap<Buf *, ErrorTableEntry *, buf_hash, buf_eql_buf> error_table;
972struct LabelTableEntry {
973 AstNode *label_node;
974 LLVMBasicBlockRef basic_block;
975 bool used;
976 bool entered_from_fallthrough;
977};980};
978981
979struct FnTableEntry {982struct FnTableEntry {
...@@ -992,8 +995,9 @@ struct FnTableEntry {...@@ -992,8 +995,9 @@ struct FnTableEntry {
992 bool is_test;995 bool is_test;
993 uint32_t ref_count; // if this is 0 we don't have to codegen it996 uint32_t ref_count; // if this is 0 we don't have to codegen it
994997
995 // reminder: hash tables must be initialized before use998 ZigList<AstNode *> cast_alloca_list;
996 HashMap<Buf *, LabelTableEntry *, buf_hash, buf_eql_buf> label_table;999 ZigList<StructValExprCodeGen *> struct_val_expr_alloca_list;
1000 ZigList<VariableTableEntry *> variable_list;
997};1001};
9981002
999enum BuiltinFnId {1003enum BuiltinFnId {
...@@ -1140,6 +1144,7 @@ struct VariableTableEntry {...@@ -1140,6 +1144,7 @@ struct VariableTableEntry {
1140 LLVMZigDILocalVariable *di_loc_var;1144 LLVMZigDILocalVariable *di_loc_var;
1141 int src_arg_index;1145 int src_arg_index;
1142 int gen_arg_index;1146 int gen_arg_index;
1147 BlockContext *block_context;
1143};1148};
11441149
1145struct ErrorTableEntry {1150struct ErrorTableEntry {
...@@ -1148,19 +1153,32 @@ struct ErrorTableEntry {...@@ -1148,19 +1153,32 @@ struct ErrorTableEntry {
1148 AstNode *decl_node;1153 AstNode *decl_node;
1149};1154};
11501155
1156enum BlockExitPath {
1157 BlockExitPathFallthrough,
1158 BlockExitPathReturn,
1159 BlockExitPathGoto,
1160};
1161
1151struct BlockContext {1162struct BlockContext {
1152 AstNode *node; // either NodeTypeFnDef or NodeTypeBlock or NodeTypeRoot1163 // One of: NodeTypeFnDef, NodeTypeBlock, NodeTypeRoot, NodeTypeDeferExpr, NodeTypeVariableDeclaration
1153 FnTableEntry *fn_entry; // null at the module scope1164 AstNode *node;
1154 BlockContext *parent; // null when this is the root1165
1166 // any variables that are introduced by this scope
1155 HashMap<Buf *, VariableTableEntry *, buf_hash, buf_eql_buf> variable_table;1167 HashMap<Buf *, VariableTableEntry *, buf_hash, buf_eql_buf> variable_table;
1156 HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> type_table;1168
1157 HashMap<Buf *, ErrorTableEntry *, buf_hash, buf_eql_buf> error_table;1169 // if the block is inside a function, this is the function it is in:
1158 ZigList<AstNode *> cast_alloca_list;1170 FnTableEntry *fn_entry;
1159 ZigList<StructValExprCodeGen *> struct_val_expr_alloca_list;1171
1160 ZigList<VariableTableEntry *> variable_list;1172 // if the block has a parent, this is it
1173 BlockContext *parent;
1174
1175 // if break or continue is valid in this context, this is the loop node that
1176 // it would pertain to
1161 AstNode *parent_loop_node;1177 AstNode *parent_loop_node;
1178
1162 LLVMZigDIScope *di_scope;1179 LLVMZigDIScope *di_scope;
1163 Buf *c_import_buf;1180 Buf *c_import_buf;
1181 bool block_exit_paths[3]; // one for each BlockExitPath
1164};1182};
11651183
1166enum CIntType {1184enum CIntType {
src/analyze.cpp+181-181
...@@ -57,6 +57,7 @@ static AstNode *first_executing_node(AstNode *node) {...@@ -57,6 +57,7 @@ static AstNode *first_executing_node(AstNode *node) {
57 case NodeTypeBlock:57 case NodeTypeBlock:
58 case NodeTypeDirective:58 case NodeTypeDirective:
59 case NodeTypeReturnExpr:59 case NodeTypeReturnExpr:
60 case NodeTypeDeferExpr:
60 case NodeTypeVariableDeclaration:61 case NodeTypeVariableDeclaration:
61 case NodeTypeTypeDecl:62 case NodeTypeTypeDecl:
62 case NodeTypeErrorValueDecl:63 case NodeTypeErrorValueDecl:
...@@ -865,23 +866,6 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t...@@ -865,23 +866,6 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t
865 }866 }
866}867}
867868
868static void preview_function_labels(CodeGen *g, AstNode *node, FnTableEntry *fn_table_entry) {
869 assert(node->type == NodeTypeBlock);
870
871 for (int i = 0; i < node->data.block.statements.length; i += 1) {
872 AstNode *label_node = node->data.block.statements.at(i);
873 if (label_node->type != NodeTypeLabel)
874 continue;
875
876 LabelTableEntry *label_entry = allocate<LabelTableEntry>(1);
877 label_entry->label_node = label_node;
878 Buf *name = &label_node->data.label.name;
879 fn_table_entry->label_table.put(name, label_entry);
880
881 label_node->data.label.label_entry = label_entry;
882 }
883}
884
885static void resolve_enum_type(CodeGen *g, ImportTableEntry *import, TypeTableEntry *enum_type) {869static void resolve_enum_type(CodeGen *g, ImportTableEntry *import, TypeTableEntry *enum_type) {
886 // if you change this logic you likely must also change similar logic in parseh.cpp870 // if you change this logic you likely must also change similar logic in parseh.cpp
887 assert(enum_type->id == TypeTableEntryIdEnum);871 assert(enum_type->id == TypeTableEntryIdEnum);
...@@ -1233,7 +1217,6 @@ static void preview_fn_proto(CodeGen *g, ImportTableEntry *import,...@@ -1233,7 +1217,6 @@ static void preview_fn_proto(CodeGen *g, ImportTableEntry *import,
1233 fn_table_entry->fn_def_node = fn_def_node;1217 fn_table_entry->fn_def_node = fn_def_node;
1234 fn_table_entry->internal_linkage = !is_c_compat;1218 fn_table_entry->internal_linkage = !is_c_compat;
1235 fn_table_entry->is_extern = is_extern;1219 fn_table_entry->is_extern = is_extern;
1236 fn_table_entry->label_table.init(8);
1237 fn_table_entry->member_of_struct = struct_type;1220 fn_table_entry->member_of_struct = struct_type;
1238 fn_table_entry->ref_count = (proto_node->data.fn_proto.visib_mod == VisibModExport) ? 1 : 0;1221 fn_table_entry->ref_count = (proto_node->data.fn_proto.visib_mod == VisibModExport) ? 1 : 0;
12391222
...@@ -1272,10 +1255,6 @@ static void preview_fn_proto(CodeGen *g, ImportTableEntry *import,...@@ -1272,10 +1255,6 @@ static void preview_fn_proto(CodeGen *g, ImportTableEntry *import,
1272 proto_node->data.fn_proto.fn_table_entry = fn_table_entry;1255 proto_node->data.fn_proto.fn_table_entry = fn_table_entry;
1273 resolve_function_proto(g, proto_node, fn_table_entry, import);1256 resolve_function_proto(g, proto_node, fn_table_entry, import);
12741257
1275 if (fn_def_node) {
1276 preview_function_labels(g, fn_def_node->data.fn_def.body, fn_table_entry);
1277 }
1278
1279 if (is_pub && !struct_type) {1258 if (is_pub && !struct_type) {
1280 for (int i = 0; i < import->importers.length; i += 1) {1259 for (int i = 0; i < import->importers.length; i += 1) {
1281 ImporterInfo importer = import->importers.at(i);1260 ImporterInfo importer = import->importers.at(i);
...@@ -1317,13 +1296,13 @@ static void resolve_error_value_decl(CodeGen *g, ImportTableEntry *import, AstNo...@@ -1317,13 +1296,13 @@ static void resolve_error_value_decl(CodeGen *g, ImportTableEntry *import, AstNo
13171296
1318 ErrorTableEntry *err = node->data.error_value_decl.err;1297 ErrorTableEntry *err = node->data.error_value_decl.err;
13191298
1320 import->block_context->error_table.put(&err->name, err);1299 import->error_table.put(&err->name, err);
13211300
1322 bool is_pub = (node->data.error_value_decl.visib_mod != VisibModPrivate);1301 bool is_pub = (node->data.error_value_decl.visib_mod != VisibModPrivate);
1323 if (is_pub) {1302 if (is_pub) {
1324 for (int i = 0; i < import->importers.length; i += 1) {1303 for (int i = 0; i < import->importers.length; i += 1) {
1325 ImporterInfo importer = import->importers.at(i);1304 ImporterInfo importer = import->importers.at(i);
1326 importer.import->block_context->error_table.put(&err->name, err);1305 importer.import->error_table.put(&err->name, err);
1327 }1306 }
1328 }1307 }
1329}1308}
...@@ -1347,6 +1326,8 @@ static void resolve_c_import_decl(CodeGen *g, ImportTableEntry *parent_import, A...@@ -1347,6 +1326,8 @@ static void resolve_c_import_decl(CodeGen *g, ImportTableEntry *parent_import, A
13471326
1348 ImportTableEntry *child_import = allocate<ImportTableEntry>(1);1327 ImportTableEntry *child_import = allocate<ImportTableEntry>(1);
1349 child_import->fn_table.init(32);1328 child_import->fn_table.init(32);
1329 child_import->type_table.init(8);
1330 child_import->error_table.init(8);
1350 child_import->c_import_node = node;1331 child_import->c_import_node = node;
13511332
1352 ZigList<ErrorMsg *> errors = {0};1333 ZigList<ErrorMsg *> errors = {0};
...@@ -1442,19 +1423,19 @@ static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode...@@ -1442,19 +1423,19 @@ static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode
1442 }1423 }
1443 }1424 }
14441425
1445 import->block_context->type_table.put(decl_name, entry);1426 import->type_table.put(decl_name, entry);
14461427
1447 bool is_pub = (node->data.type_decl.visib_mod != VisibModPrivate);1428 bool is_pub = (node->data.type_decl.visib_mod != VisibModPrivate);
1448 if (is_pub) {1429 if (is_pub) {
1449 for (int i = 0; i < import->importers.length; i += 1) {1430 for (int i = 0; i < import->importers.length; i += 1) {
1450 ImporterInfo importer = import->importers.at(i);1431 ImporterInfo importer = import->importers.at(i);
1451 auto table_entry = importer.import->block_context->type_table.maybe_get(&entry->name);1432 auto table_entry = importer.import->type_table.maybe_get(&entry->name);
1452 if (table_entry) {1433 if (table_entry) {
1453 add_node_error(g, importer.source_node,1434 add_node_error(g, importer.source_node,
1454 buf_sprintf("import of type '%s' overrides existing definition",1435 buf_sprintf("import of type '%s' overrides existing definition",
1455 buf_ptr(&entry->name)));1436 buf_ptr(&entry->name)));
1456 } else {1437 } else {
1457 importer.import->block_context->type_table.put(&entry->name, entry);1438 importer.import->type_table.put(&entry->name, entry);
1458 }1439 }
1459 }1440 }
1460 }1441 }
...@@ -1475,6 +1456,7 @@ static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode...@@ -1475,6 +1456,7 @@ static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode
1475 case NodeTypeParamDecl:1456 case NodeTypeParamDecl:
1476 case NodeTypeFnDecl:1457 case NodeTypeFnDecl:
1477 case NodeTypeReturnExpr:1458 case NodeTypeReturnExpr:
1459 case NodeTypeDeferExpr:
1478 case NodeTypeRoot:1460 case NodeTypeRoot:
1479 case NodeTypeBlock:1461 case NodeTypeBlock:
1480 case NodeTypeBinOpExpr:1462 case NodeTypeBinOpExpr:
...@@ -1953,9 +1935,7 @@ BlockContext *new_block_context(AstNode *node, BlockContext *parent) {...@@ -1953,9 +1935,7 @@ BlockContext *new_block_context(AstNode *node, BlockContext *parent) {
1953 BlockContext *context = allocate<BlockContext>(1);1935 BlockContext *context = allocate<BlockContext>(1);
1954 context->node = node;1936 context->node = node;
1955 context->parent = parent;1937 context->parent = parent;
1956 context->variable_table.init(8);1938 context->variable_table.init(4);
1957 context->type_table.init(8);
1958 context->error_table.init(8);
19591939
1960 if (parent) {1940 if (parent) {
1961 context->parent_loop_node = parent->parent_loop_node;1941 context->parent_loop_node = parent->parent_loop_node;
...@@ -1976,10 +1956,10 @@ BlockContext *new_block_context(AstNode *node, BlockContext *parent) {...@@ -1976,10 +1956,10 @@ BlockContext *new_block_context(AstNode *node, BlockContext *parent) {
1976 return context;1956 return context;
1977}1957}
19781958
1979static VariableTableEntry *find_local_variable(BlockContext *context, Buf *name) {1959static VariableTableEntry *find_variable(BlockContext *context, Buf *name, bool local_only) {
1980 while (context && context->fn_entry) {1960 while (context && (!local_only || context->fn_entry)) {
1981 auto entry = context->variable_table.maybe_get(name);1961 auto entry = context->variable_table.maybe_get(name);
1982 if (entry != nullptr)1962 if (entry)
1983 return entry->value;1963 return entry->value;
19841964
1985 context = context->parent;1965 context = context->parent;
...@@ -1987,26 +1967,12 @@ static VariableTableEntry *find_local_variable(BlockContext *context, Buf *name)...@@ -1987,26 +1967,12 @@ static VariableTableEntry *find_local_variable(BlockContext *context, Buf *name)
1987 return nullptr;1967 return nullptr;
1988}1968}
19891969
1990VariableTableEntry *find_variable(BlockContext *context, Buf *name) {1970static TypeTableEntry *find_container(ImportTableEntry *import, Buf *name) {
1991 while (context) {1971 auto entry = import->type_table.maybe_get(name);
1992 auto entry = context->variable_table.maybe_get(name);1972 if (entry)
1993 if (entry != nullptr)1973 return entry->value;
1994 return entry->value;1974 else
19951975 return nullptr;
1996 context = context->parent;
1997 }
1998 return nullptr;
1999}
2000
2001TypeTableEntry *find_container(BlockContext *context, Buf *name) {
2002 while (context) {
2003 auto entry = context->type_table.maybe_get(name);
2004 if (entry != nullptr)
2005 return entry->value;
2006
2007 context = context->parent;
2008 }
2009 return nullptr;
2010}1976}
20111977
2012static TypeEnumField *get_enum_field(TypeTableEntry *enum_type, Buf *name) {1978static TypeEnumField *get_enum_field(TypeTableEntry *enum_type, Buf *name) {
...@@ -2034,7 +2000,7 @@ static TypeTableEntry *analyze_enum_value_expr(CodeGen *g, ImportTableEntry *imp...@@ -2034,7 +2000,7 @@ static TypeTableEntry *analyze_enum_value_expr(CodeGen *g, ImportTableEntry *imp
2034 StructValExprCodeGen *codegen = &field_access_node->data.field_access_expr.resolved_struct_val_expr;2000 StructValExprCodeGen *codegen = &field_access_node->data.field_access_expr.resolved_struct_val_expr;
2035 codegen->type_entry = enum_type;2001 codegen->type_entry = enum_type;
2036 codegen->source_node = field_access_node;2002 codegen->source_node = field_access_node;
2037 context->struct_val_expr_alloca_list.append(codegen);2003 context->fn_entry->struct_val_expr_alloca_list.append(codegen);
20382004
2039 Expr *expr = get_resolved_expr(field_access_node);2005 Expr *expr = get_resolved_expr(field_access_node);
2040 expr->const_val.ok = false;2006 expr->const_val.ok = false;
...@@ -2099,7 +2065,6 @@ static TypeTableEntry *analyze_container_init_expr(CodeGen *g, ImportTableEntry...@@ -2099,7 +2065,6 @@ static TypeTableEntry *analyze_container_init_expr(CodeGen *g, ImportTableEntry
2099 StructValExprCodeGen *codegen = &container_init_expr->resolved_struct_val_expr;2065 StructValExprCodeGen *codegen = &container_init_expr->resolved_struct_val_expr;
2100 codegen->type_entry = container_type;2066 codegen->type_entry = container_type;
2101 codegen->source_node = node;2067 codegen->source_node = node;
2102 context->struct_val_expr_alloca_list.append(codegen);
21032068
21042069
2105 int expr_field_count = container_init_expr->entries.length;2070 int expr_field_count = container_init_expr->entries.length;
...@@ -2150,6 +2115,9 @@ static TypeTableEntry *analyze_container_init_expr(CodeGen *g, ImportTableEntry...@@ -2150,6 +2115,9 @@ static TypeTableEntry *analyze_container_init_expr(CodeGen *g, ImportTableEntry
2150 const_val->ok = false;2115 const_val->ok = false;
2151 }2116 }
2152 }2117 }
2118 if (!const_val->ok) {
2119 context->fn_entry->struct_val_expr_alloca_list.append(codegen);
2120 }
2153 }2121 }
21542122
2155 for (int i = 0; i < actual_field_count; i += 1) {2123 for (int i = 0; i < actual_field_count; i += 1) {
...@@ -2192,7 +2160,9 @@ static TypeTableEntry *analyze_container_init_expr(CodeGen *g, ImportTableEntry...@@ -2192,7 +2160,9 @@ static TypeTableEntry *analyze_container_init_expr(CodeGen *g, ImportTableEntry
2192 StructValExprCodeGen *codegen = &container_init_expr->resolved_struct_val_expr;2160 StructValExprCodeGen *codegen = &container_init_expr->resolved_struct_val_expr;
2193 codegen->type_entry = fixed_size_array_type;2161 codegen->type_entry = fixed_size_array_type;
2194 codegen->source_node = node;2162 codegen->source_node = node;
2195 context->struct_val_expr_alloca_list.append(codegen);2163 if (!const_val->ok) {
2164 context->fn_entry->struct_val_expr_alloca_list.append(codegen);
2165 }
21962166
2197 return fixed_size_array_type;2167 return fixed_size_array_type;
2198 } else if (container_type->id == TypeTableEntryIdArray) {2168 } else if (container_type->id == TypeTableEntryIdArray) {
...@@ -2339,7 +2309,7 @@ static TypeTableEntry *analyze_slice_expr(CodeGen *g, ImportTableEntry *import,...@@ -2339,7 +2309,7 @@ static TypeTableEntry *analyze_slice_expr(CodeGen *g, ImportTableEntry *import,
2339 if (return_type->id != TypeTableEntryIdInvalid) {2309 if (return_type->id != TypeTableEntryIdInvalid) {
2340 node->data.slice_expr.resolved_struct_val_expr.type_entry = return_type;2310 node->data.slice_expr.resolved_struct_val_expr.type_entry = return_type;
2341 node->data.slice_expr.resolved_struct_val_expr.source_node = node;2311 node->data.slice_expr.resolved_struct_val_expr.source_node = node;
2342 context->struct_val_expr_alloca_list.append(&node->data.slice_expr.resolved_struct_val_expr);2312 context->fn_entry->struct_val_expr_alloca_list.append(&node->data.slice_expr.resolved_struct_val_expr);
2343 }2313 }
23442314
2345 analyze_expression(g, import, context, g->builtin_types.entry_isize, node->data.slice_expr.start);2315 analyze_expression(g, import, context, g->builtin_types.entry_isize, node->data.slice_expr.start);
...@@ -2518,7 +2488,7 @@ static TypeTableEntry *resolve_expr_const_val_as_bignum_op(CodeGen *g, AstNode *...@@ -2518,7 +2488,7 @@ static TypeTableEntry *resolve_expr_const_val_as_bignum_op(CodeGen *g, AstNode *
2518static TypeTableEntry *analyze_error_literal_expr(CodeGen *g, ImportTableEntry *import,2488static TypeTableEntry *analyze_error_literal_expr(CodeGen *g, ImportTableEntry *import,
2519 BlockContext *context, AstNode *node, Buf *err_name)2489 BlockContext *context, AstNode *node, Buf *err_name)
2520{2490{
2521 auto err_table_entry = import->block_context->error_table.maybe_get(err_name);2491 auto err_table_entry = import->error_table.maybe_get(err_name);
25222492
2523 if (err_table_entry) {2493 if (err_table_entry) {
2524 return resolve_expr_const_val_as_err(g, node, err_table_entry->value);2494 return resolve_expr_const_val_as_err(g, node, err_table_entry->value);
...@@ -2545,7 +2515,7 @@ static TypeTableEntry *analyze_symbol_expr(CodeGen *g, ImportTableEntry *import,...@@ -2545,7 +2515,7 @@ static TypeTableEntry *analyze_symbol_expr(CodeGen *g, ImportTableEntry *import,
2545 return resolve_expr_const_val_as_type(g, node, primitive_table_entry->value);2515 return resolve_expr_const_val_as_type(g, node, primitive_table_entry->value);
2546 }2516 }
25472517
2548 VariableTableEntry *var = find_variable(context, variable_name);2518 VariableTableEntry *var = find_variable(context, variable_name, false);
2549 if (var) {2519 if (var) {
2550 node->data.symbol_expr.variable = var;2520 node->data.symbol_expr.variable = var;
2551 if (var->is_const) {2521 if (var->is_const) {
...@@ -2561,7 +2531,7 @@ static TypeTableEntry *analyze_symbol_expr(CodeGen *g, ImportTableEntry *import,...@@ -2561,7 +2531,7 @@ static TypeTableEntry *analyze_symbol_expr(CodeGen *g, ImportTableEntry *import,
2561 return var->type;2531 return var->type;
2562 }2532 }
25632533
2564 TypeTableEntry *container_type = find_container(context, variable_name);2534 TypeTableEntry *container_type = find_container(import, variable_name);
2565 if (container_type) {2535 if (container_type) {
2566 return resolve_expr_const_val_as_type(g, node, container_type);2536 return resolve_expr_const_val_as_type(g, node, container_type);
2567 }2537 }
...@@ -2641,7 +2611,7 @@ static TypeTableEntry *analyze_lvalue(CodeGen *g, ImportTableEntry *import, Bloc...@@ -2641,7 +2611,7 @@ static TypeTableEntry *analyze_lvalue(CodeGen *g, ImportTableEntry *import, Bloc
2641 if (purpose == LValPurposeAddressOf) {2611 if (purpose == LValPurposeAddressOf) {
2642 expected_rhs_type = analyze_symbol_expr(g, import, block_context, nullptr, lhs_node);2612 expected_rhs_type = analyze_symbol_expr(g, import, block_context, nullptr, lhs_node);
2643 } else {2613 } else {
2644 VariableTableEntry *var = find_variable(block_context, name);2614 VariableTableEntry *var = find_variable(block_context, name, false);
2645 if (var) {2615 if (var) {
2646 if (var->is_const) {2616 if (var->is_const) {
2647 add_node_error(g, lhs_node, buf_sprintf("cannot assign to constant"));2617 add_node_error(g, lhs_node, buf_sprintf("cannot assign to constant"));
...@@ -3011,21 +2981,18 @@ static TypeTableEntry *analyze_bin_op_expr(CodeGen *g, ImportTableEntry *import,...@@ -3011,21 +2981,18 @@ static TypeTableEntry *analyze_bin_op_expr(CodeGen *g, ImportTableEntry *import,
3011}2981}
30122982
3013// Set name to nullptr to make the variable anonymous (not visible to programmer).2983// Set name to nullptr to make the variable anonymous (not visible to programmer).
3014static VariableTableEntry *add_local_var(CodeGen *g, AstNode *source_node, BlockContext *context,2984static VariableTableEntry *add_local_var(CodeGen *g, AstNode *source_node, ImportTableEntry *import,
3015 Buf *name, TypeTableEntry *type_entry, bool is_const)2985 BlockContext *context, Buf *name, TypeTableEntry *type_entry, bool is_const)
3016{2986{
3017 VariableTableEntry *variable_entry = allocate<VariableTableEntry>(1);2987 VariableTableEntry *variable_entry = allocate<VariableTableEntry>(1);
3018 variable_entry->type = type_entry;2988 variable_entry->type = type_entry;
2989 variable_entry->block_context = context;
30192990
3020 if (name) {2991 if (name) {
3021 buf_init_from_buf(&variable_entry->name, name);2992 buf_init_from_buf(&variable_entry->name, name);
3022 VariableTableEntry *existing_var;2993 VariableTableEntry *existing_var;
30232994
3024 if (context->fn_entry) {2995 existing_var = find_variable(context, name, context->fn_entry != nullptr);
3025 existing_var = find_local_variable(context, name);
3026 } else {
3027 existing_var = find_variable(context, name);
3028 }
30292996
3030 if (existing_var) {2997 if (existing_var) {
3031 add_node_error(g, source_node, buf_sprintf("redeclaration of variable '%s'", buf_ptr(name)));2998 add_node_error(g, source_node, buf_sprintf("redeclaration of variable '%s'", buf_ptr(name)));
...@@ -3036,7 +3003,7 @@ static VariableTableEntry *add_local_var(CodeGen *g, AstNode *source_node, Block...@@ -3036,7 +3003,7 @@ static VariableTableEntry *add_local_var(CodeGen *g, AstNode *source_node, Block
3036 if (primitive_table_entry) {3003 if (primitive_table_entry) {
3037 type = primitive_table_entry->value;3004 type = primitive_table_entry->value;
3038 } else {3005 } else {
3039 type = find_container(context, name);3006 type = find_container(import, name);
3040 }3007 }
3041 if (type) {3008 if (type) {
3042 add_node_error(g, source_node, buf_sprintf("variable shadows type '%s'", buf_ptr(&type->name)));3009 add_node_error(g, source_node, buf_sprintf("variable shadows type '%s'", buf_ptr(&type->name)));
...@@ -3045,10 +3012,11 @@ static VariableTableEntry *add_local_var(CodeGen *g, AstNode *source_node, Block...@@ -3045,10 +3012,11 @@ static VariableTableEntry *add_local_var(CodeGen *g, AstNode *source_node, Block
3045 }3012 }
30463013
3047 context->variable_table.put(&variable_entry->name, variable_entry);3014 context->variable_table.put(&variable_entry->name, variable_entry);
3048 context->variable_list.append(variable_entry);
3049 } else {3015 } else {
3050 buf_init_from_str(&variable_entry->name, "_anon");3016 buf_init_from_str(&variable_entry->name, "_anon");
3051 context->variable_list.append(variable_entry);3017 }
3018 if (context->fn_entry) {
3019 context->fn_entry->variable_list.append(variable_entry);
3052 }3020 }
30533021
3054 variable_entry->is_const = is_const;3022 variable_entry->is_const = is_const;
...@@ -3075,7 +3043,7 @@ static TypeTableEntry *analyze_unwrap_error_expr(CodeGen *g, ImportTableEntry *i...@@ -3075,7 +3043,7 @@ static TypeTableEntry *analyze_unwrap_error_expr(CodeGen *g, ImportTableEntry *i
3075 child_context = new_block_context(node, parent_context);3043 child_context = new_block_context(node, parent_context);
3076 var_node->block_context = child_context;3044 var_node->block_context = child_context;
3077 Buf *var_name = &var_node->data.symbol_expr.symbol;3045 Buf *var_name = &var_node->data.symbol_expr.symbol;
3078 node->data.unwrap_err_expr.var = add_local_var(g, var_node, child_context, var_name,3046 node->data.unwrap_err_expr.var = add_local_var(g, var_node, import, child_context, var_name,
3079 g->builtin_types.entry_pure_error, true);3047 g->builtin_types.entry_pure_error, true);
3080 } else {3048 } else {
3081 child_context = parent_context;3049 child_context = parent_context;
...@@ -3153,7 +3121,7 @@ static VariableTableEntry *analyze_variable_declaration_raw(CodeGen *g, ImportTa...@@ -3153,7 +3121,7 @@ static VariableTableEntry *analyze_variable_declaration_raw(CodeGen *g, ImportTa
3153 TypeTableEntry *type = explicit_type != nullptr ? explicit_type : implicit_type;3121 TypeTableEntry *type = explicit_type != nullptr ? explicit_type : implicit_type;
3154 assert(type != nullptr); // should have been caught by the parser3122 assert(type != nullptr); // should have been caught by the parser
31553123
3156 VariableTableEntry *var = add_local_var(g, source_node, context,3124 VariableTableEntry *var = add_local_var(g, source_node, import, context,
3157 &variable_declaration->symbol, type, is_const);3125 &variable_declaration->symbol, type, is_const);
31583126
3159 variable_declaration->variable = var;3127 variable_declaration->variable = var;
...@@ -3199,7 +3167,7 @@ static TypeTableEntry *analyze_null_literal_expr(CodeGen *g, ImportTableEntry *i...@@ -3199,7 +3167,7 @@ static TypeTableEntry *analyze_null_literal_expr(CodeGen *g, ImportTableEntry *i
31993167
3200 node->data.null_literal.resolved_struct_val_expr.type_entry = expected_type;3168 node->data.null_literal.resolved_struct_val_expr.type_entry = expected_type;
3201 node->data.null_literal.resolved_struct_val_expr.source_node = node;3169 node->data.null_literal.resolved_struct_val_expr.source_node = node;
3202 block_context->struct_val_expr_alloca_list.append(&node->data.null_literal.resolved_struct_val_expr);3170 block_context->fn_entry->struct_val_expr_alloca_list.append(&node->data.null_literal.resolved_struct_val_expr);
32033171
3204 return resolve_expr_const_val_as_null(g, node, expected_type);3172 return resolve_expr_const_val_as_null(g, node, expected_type);
3205}3173}
...@@ -3303,7 +3271,6 @@ static TypeTableEntry *analyze_while_expr(CodeGen *g, ImportTableEntry *import,...@@ -3303,7 +3271,6 @@ static TypeTableEntry *analyze_while_expr(CodeGen *g, ImportTableEntry *import,
33033271
3304 BlockContext *child_context = new_block_context(node, context);3272 BlockContext *child_context = new_block_context(node, context);
3305 child_context->parent_loop_node = node;3273 child_context->parent_loop_node = node;
3306 node->data.while_expr.block_context = child_context;
33073274
3308 analyze_expression(g, import, child_context, g->builtin_types.entry_void, while_body_node);3275 analyze_expression(g, import, child_context, g->builtin_types.entry_void, while_body_node);
33093276
...@@ -3359,16 +3326,16 @@ static TypeTableEntry *analyze_for_expr(CodeGen *g, ImportTableEntry *import, Bl...@@ -3359,16 +3326,16 @@ static TypeTableEntry *analyze_for_expr(CodeGen *g, ImportTableEntry *import, Bl
3359 AstNode *elem_var_node = node->data.for_expr.elem_node;3326 AstNode *elem_var_node = node->data.for_expr.elem_node;
3360 elem_var_node->block_context = child_context;3327 elem_var_node->block_context = child_context;
3361 Buf *elem_var_name = &elem_var_node->data.symbol_expr.symbol;3328 Buf *elem_var_name = &elem_var_node->data.symbol_expr.symbol;
3362 node->data.for_expr.elem_var = add_local_var(g, elem_var_node, child_context, elem_var_name, child_type, true);3329 node->data.for_expr.elem_var = add_local_var(g, elem_var_node, import, child_context, elem_var_name, child_type, true);
33633330
3364 AstNode *index_var_node = node->data.for_expr.index_node;3331 AstNode *index_var_node = node->data.for_expr.index_node;
3365 if (index_var_node) {3332 if (index_var_node) {
3366 Buf *index_var_name = &index_var_node->data.symbol_expr.symbol;3333 Buf *index_var_name = &index_var_node->data.symbol_expr.symbol;
3367 index_var_node->block_context = child_context;3334 index_var_node->block_context = child_context;
3368 node->data.for_expr.index_var = add_local_var(g, index_var_node, child_context, index_var_name,3335 node->data.for_expr.index_var = add_local_var(g, index_var_node, import, child_context, index_var_name,
3369 g->builtin_types.entry_isize, true);3336 g->builtin_types.entry_isize, true);
3370 } else {3337 } else {
3371 node->data.for_expr.index_var = add_local_var(g, node, child_context, nullptr,3338 node->data.for_expr.index_var = add_local_var(g, node, import, child_context, nullptr,
3372 g->builtin_types.entry_isize, true);3339 g->builtin_types.entry_isize, true);
3373 }3340 }
33743341
...@@ -3617,6 +3584,21 @@ static void eval_const_expr_implicit_cast(CodeGen *g, AstNode *node, AstNode *ex...@@ -3617,6 +3584,21 @@ static void eval_const_expr_implicit_cast(CodeGen *g, AstNode *node, AstNode *ex
3617 }3584 }
3618}3585}
36193586
3587static TypeTableEntry *resolve_cast(CodeGen *g, BlockContext *context, AstNode *node,
3588 AstNode *expr_node, TypeTableEntry *wanted_type, CastOp op, bool need_alloca)
3589{
3590 node->data.fn_call_expr.cast_op = op;
3591 eval_const_expr_implicit_cast(g, node, expr_node);
3592 if (need_alloca) {
3593 if (context->fn_entry) {
3594 context->fn_entry->cast_alloca_list.append(node);
3595 } else {
3596 assert(get_resolved_expr(node)->const_val.ok);
3597 }
3598 }
3599 return wanted_type;
3600}
3601
3620static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,3602static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
3621 AstNode *node)3603 AstNode *node)
3622{3604{
...@@ -3642,27 +3624,21 @@ static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, B...@@ -3642,27 +3624,21 @@ static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, B
36423624
3643 // explicit match or non-const to const3625 // explicit match or non-const to const
3644 if (types_match_const_cast_only(wanted_type, actual_type)) {3626 if (types_match_const_cast_only(wanted_type, actual_type)) {
3645 node->data.fn_call_expr.cast_op = CastOpNoop;3627 return resolve_cast(g, context, node, expr_node, wanted_type, CastOpNoop, false);
3646 eval_const_expr_implicit_cast(g, node, expr_node);
3647 return wanted_type;
3648 }3628 }
36493629
3650 // explicit cast from bool to int3630 // explicit cast from bool to int
3651 if (wanted_type->id == TypeTableEntryIdInt &&3631 if (wanted_type->id == TypeTableEntryIdInt &&
3652 actual_type->id == TypeTableEntryIdBool)3632 actual_type->id == TypeTableEntryIdBool)
3653 {3633 {
3654 node->data.fn_call_expr.cast_op = CastOpBoolToInt;3634 return resolve_cast(g, context, node, expr_node, wanted_type, CastOpBoolToInt, false);
3655 eval_const_expr_implicit_cast(g, node, expr_node);
3656 return wanted_type;
3657 }3635 }
36583636
3659 // explicit cast from pointer to isize or usize3637 // explicit cast from pointer to isize or usize
3660 if ((wanted_type == g->builtin_types.entry_isize || wanted_type == g->builtin_types.entry_usize) &&3638 if ((wanted_type == g->builtin_types.entry_isize || wanted_type == g->builtin_types.entry_usize) &&
3661 actual_type->id == TypeTableEntryIdPointer)3639 actual_type->id == TypeTableEntryIdPointer)
3662 {3640 {
3663 node->data.fn_call_expr.cast_op = CastOpPtrToInt;3641 return resolve_cast(g, context, node, expr_node, wanted_type, CastOpPtrToInt, false);
3664 eval_const_expr_implicit_cast(g, node, expr_node);
3665 return wanted_type;
3666 }3642 }
36673643
36683644
...@@ -3670,9 +3646,7 @@ static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, B...@@ -3670,9 +3646,7 @@ static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, B
3670 if (wanted_type->id == TypeTableEntryIdPointer &&3646 if (wanted_type->id == TypeTableEntryIdPointer &&
3671 (actual_type == g->builtin_types.entry_isize || actual_type == g->builtin_types.entry_usize))3647 (actual_type == g->builtin_types.entry_isize || actual_type == g->builtin_types.entry_usize))
3672 {3648 {
3673 node->data.fn_call_expr.cast_op = CastOpIntToPtr;3649 return resolve_cast(g, context, node, expr_node, wanted_type, CastOpIntToPtr, false);
3674 eval_const_expr_implicit_cast(g, node, expr_node);
3675 return wanted_type;
3676 }3650 }
36773651
3678 // explicit widening or shortening cast3652 // explicit widening or shortening cast
...@@ -3681,27 +3655,21 @@ static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, B...@@ -3681,27 +3655,21 @@ static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, B
3681 (wanted_type->id == TypeTableEntryIdFloat &&3655 (wanted_type->id == TypeTableEntryIdFloat &&
3682 actual_type->id == TypeTableEntryIdFloat))3656 actual_type->id == TypeTableEntryIdFloat))
3683 {3657 {
3684 node->data.fn_call_expr.cast_op = CastOpWidenOrShorten;3658 return resolve_cast(g, context, node, expr_node, wanted_type, CastOpWidenOrShorten, false);
3685 eval_const_expr_implicit_cast(g, node, expr_node);
3686 return wanted_type;
3687 }3659 }
36883660
3689 // explicit cast from int to float3661 // explicit cast from int to float
3690 if (wanted_type->id == TypeTableEntryIdFloat &&3662 if (wanted_type->id == TypeTableEntryIdFloat &&
3691 actual_type->id == TypeTableEntryIdInt)3663 actual_type->id == TypeTableEntryIdInt)
3692 {3664 {
3693 node->data.fn_call_expr.cast_op = CastOpIntToFloat;3665 return resolve_cast(g, context, node, expr_node, wanted_type, CastOpIntToFloat, false);
3694 eval_const_expr_implicit_cast(g, node, expr_node);
3695 return wanted_type;
3696 }3666 }
36973667
3698 // explicit cast from float to int3668 // explicit cast from float to int
3699 if (wanted_type->id == TypeTableEntryIdInt &&3669 if (wanted_type->id == TypeTableEntryIdInt &&
3700 actual_type->id == TypeTableEntryIdFloat)3670 actual_type->id == TypeTableEntryIdFloat)
3701 {3671 {
3702 node->data.fn_call_expr.cast_op = CastOpFloatToInt;3672 return resolve_cast(g, context, node, expr_node, wanted_type, CastOpFloatToInt, false);
3703 eval_const_expr_implicit_cast(g, node, expr_node);
3704 return wanted_type;
3705 }3673 }
37063674
3707 // explicit cast from fixed size array to unknown size array3675 // explicit cast from fixed size array to unknown size array
...@@ -3712,36 +3680,25 @@ static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, B...@@ -3712,36 +3680,25 @@ static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, B
3712 wanted_type->data.structure.fields[0].type_entry->data.pointer.child_type,3680 wanted_type->data.structure.fields[0].type_entry->data.pointer.child_type,
3713 actual_type->data.array.child_type))3681 actual_type->data.array.child_type))
3714 {3682 {
3715 node->data.fn_call_expr.cast_op = CastOpToUnknownSizeArray;3683 return resolve_cast(g, context, node, expr_node, wanted_type, CastOpToUnknownSizeArray, true);
3716 context->cast_alloca_list.append(node);
3717 eval_const_expr_implicit_cast(g, node, expr_node);
3718 return wanted_type;
3719 }3684 }
37203685
3721 // explicit cast from pointer to another pointer3686 // explicit cast from pointer to another pointer
3722 if (actual_type->id == TypeTableEntryIdPointer &&3687 if (actual_type->id == TypeTableEntryIdPointer &&
3723 wanted_type->id == TypeTableEntryIdPointer)3688 wanted_type->id == TypeTableEntryIdPointer)
3724 {3689 {
3725 node->data.fn_call_expr.cast_op = CastOpPointerReinterpret;3690 return resolve_cast(g, context, node, expr_node, wanted_type, CastOpPointerReinterpret, false);
3726 eval_const_expr_implicit_cast(g, node, expr_node);
3727 return wanted_type;
3728 }3691 }
37293692
3730 // explicit cast from child type of maybe type to maybe type3693 // explicit cast from child type of maybe type to maybe type
3731 if (wanted_type->id == TypeTableEntryIdMaybe) {3694 if (wanted_type->id == TypeTableEntryIdMaybe) {
3732 if (types_match_const_cast_only(wanted_type->data.maybe.child_type, actual_type)) {3695 if (types_match_const_cast_only(wanted_type->data.maybe.child_type, actual_type)) {
3733 node->data.fn_call_expr.cast_op = CastOpMaybeWrap;3696 return resolve_cast(g, context, node, expr_node, wanted_type, CastOpMaybeWrap, true);
3734 context->cast_alloca_list.append(node);
3735 eval_const_expr_implicit_cast(g, node, expr_node);
3736 return wanted_type;
3737 } else if (actual_type->id == TypeTableEntryIdNumLitInt ||3697 } else if (actual_type->id == TypeTableEntryIdNumLitInt ||
3738 actual_type->id == TypeTableEntryIdNumLitFloat)3698 actual_type->id == TypeTableEntryIdNumLitFloat)
3739 {3699 {
3740 if (num_lit_fits_in_other_type(g, expr_node, wanted_type->data.maybe.child_type)) {3700 if (num_lit_fits_in_other_type(g, expr_node, wanted_type->data.maybe.child_type)) {
3741 node->data.fn_call_expr.cast_op = CastOpMaybeWrap;3701 return resolve_cast(g, context, node, expr_node, wanted_type, CastOpMaybeWrap, true);
3742 context->cast_alloca_list.append(node);
3743 eval_const_expr_implicit_cast(g, node, expr_node);
3744 return wanted_type;
3745 } else {3702 } else {
3746 return g->builtin_types.entry_invalid;3703 return g->builtin_types.entry_invalid;
3747 }3704 }
...@@ -3751,18 +3708,12 @@ static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, B...@@ -3751,18 +3708,12 @@ static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, B
3751 // explicit cast from child type of error type to error type3708 // explicit cast from child type of error type to error type
3752 if (wanted_type->id == TypeTableEntryIdErrorUnion) {3709 if (wanted_type->id == TypeTableEntryIdErrorUnion) {
3753 if (types_match_const_cast_only(wanted_type->data.error.child_type, actual_type)) {3710 if (types_match_const_cast_only(wanted_type->data.error.child_type, actual_type)) {
3754 node->data.fn_call_expr.cast_op = CastOpErrorWrap;3711 return resolve_cast(g, context, node, expr_node, wanted_type, CastOpErrorWrap, true);
3755 context->cast_alloca_list.append(node);
3756 eval_const_expr_implicit_cast(g, node, expr_node);
3757 return wanted_type;
3758 } else if (actual_type->id == TypeTableEntryIdNumLitInt ||3712 } else if (actual_type->id == TypeTableEntryIdNumLitInt ||
3759 actual_type->id == TypeTableEntryIdNumLitFloat)3713 actual_type->id == TypeTableEntryIdNumLitFloat)
3760 {3714 {
3761 if (num_lit_fits_in_other_type(g, expr_node, wanted_type->data.error.child_type)) {3715 if (num_lit_fits_in_other_type(g, expr_node, wanted_type->data.error.child_type)) {
3762 node->data.fn_call_expr.cast_op = CastOpErrorWrap;3716 return resolve_cast(g, context, node, expr_node, wanted_type, CastOpErrorWrap, true);
3763 context->cast_alloca_list.append(node);
3764 eval_const_expr_implicit_cast(g, node, expr_node);
3765 return wanted_type;
3766 } else {3717 } else {
3767 return g->builtin_types.entry_invalid;3718 return g->builtin_types.entry_invalid;
3768 }3719 }
...@@ -3773,9 +3724,7 @@ static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, B...@@ -3773,9 +3724,7 @@ static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, B
3773 if (wanted_type->id == TypeTableEntryIdErrorUnion &&3724 if (wanted_type->id == TypeTableEntryIdErrorUnion &&
3774 actual_type->id == TypeTableEntryIdPureError)3725 actual_type->id == TypeTableEntryIdPureError)
3775 {3726 {
3776 node->data.fn_call_expr.cast_op = CastOpPureErrorWrap;3727 return resolve_cast(g, context, node, expr_node, wanted_type, CastOpPureErrorWrap, false);
3777 eval_const_expr_implicit_cast(g, node, expr_node);
3778 return wanted_type;
3779 }3728 }
37803729
3781 // explicit cast from number literal to another type3730 // explicit cast from number literal to another type
...@@ -3783,21 +3732,21 @@ static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, B...@@ -3783,21 +3732,21 @@ static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, B
3783 actual_type->id == TypeTableEntryIdNumLitInt)3732 actual_type->id == TypeTableEntryIdNumLitInt)
3784 {3733 {
3785 if (num_lit_fits_in_other_type(g, expr_node, wanted_type)) {3734 if (num_lit_fits_in_other_type(g, expr_node, wanted_type)) {
3735 CastOp op;
3786 if ((actual_type->id == TypeTableEntryIdNumLitFloat &&3736 if ((actual_type->id == TypeTableEntryIdNumLitFloat &&
3787 wanted_type->id == TypeTableEntryIdFloat) ||3737 wanted_type->id == TypeTableEntryIdFloat) ||
3788 (actual_type->id == TypeTableEntryIdNumLitInt &&3738 (actual_type->id == TypeTableEntryIdNumLitInt &&
3789 wanted_type->id == TypeTableEntryIdInt))3739 wanted_type->id == TypeTableEntryIdInt))
3790 {3740 {
3791 node->data.fn_call_expr.cast_op = CastOpNoop;3741 op = CastOpNoop;
3792 } else if (wanted_type->id == TypeTableEntryIdInt) {3742 } else if (wanted_type->id == TypeTableEntryIdInt) {
3793 node->data.fn_call_expr.cast_op = CastOpFloatToInt;3743 op = CastOpFloatToInt;
3794 } else if (wanted_type->id == TypeTableEntryIdFloat) {3744 } else if (wanted_type->id == TypeTableEntryIdFloat) {
3795 node->data.fn_call_expr.cast_op = CastOpIntToFloat;3745 op = CastOpIntToFloat;
3796 } else {3746 } else {
3797 zig_unreachable();3747 zig_unreachable();
3798 }3748 }
3799 eval_const_expr_implicit_cast(g, node, expr_node);3749 return resolve_cast(g, context, node, expr_node, wanted_type, op, false);
3800 return wanted_type;
3801 } else {3750 } else {
3802 return g->builtin_types.entry_invalid;3751 return g->builtin_types.entry_invalid;
3803 }3752 }
...@@ -3815,9 +3764,7 @@ static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, B...@@ -3815,9 +3764,7 @@ static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, B
3815 if (bignum_fits_in_bits(&bn, wanted_type->data.integral.bit_count,3764 if (bignum_fits_in_bits(&bn, wanted_type->data.integral.bit_count,
3816 wanted_type->data.integral.is_signed))3765 wanted_type->data.integral.is_signed))
3817 {3766 {
3818 node->data.fn_call_expr.cast_op = CastOpErrToInt;3767 return resolve_cast(g, context, node, expr_node, wanted_type, CastOpErrToInt, false);
3819 eval_const_expr_implicit_cast(g, node, expr_node);
3820 return wanted_type;
3821 } else {3768 } else {
3822 add_node_error(g, node,3769 add_node_error(g, node,
3823 buf_sprintf("too many error values to fit in '%s'", buf_ptr(&wanted_type->name)));3770 buf_sprintf("too many error values to fit in '%s'", buf_ptr(&wanted_type->name)));
...@@ -4176,7 +4123,7 @@ static TypeTableEntry *analyze_fn_call_ptr(CodeGen *g, ImportTableEntry *import,...@@ -4176,7 +4123,7 @@ static TypeTableEntry *analyze_fn_call_ptr(CodeGen *g, ImportTableEntry *import,
4176 }4123 }
41774124
4178 if (handle_is_ptr(return_type)) {4125 if (handle_is_ptr(return_type)) {
4179 context->cast_alloca_list.append(node);4126 context->fn_entry->cast_alloca_list.append(node);
4180 }4127 }
41814128
4182 return return_type;4129 return return_type;
...@@ -4572,8 +4519,8 @@ static TypeTableEntry *analyze_switch_expr(CodeGen *g, ImportTableEntry *import,...@@ -4572,8 +4519,8 @@ static TypeTableEntry *analyze_switch_expr(CodeGen *g, ImportTableEntry *import,
4572 assert(var_node->type == NodeTypeSymbol);4519 assert(var_node->type == NodeTypeSymbol);
4573 Buf *var_name = &var_node->data.symbol_expr.symbol;4520 Buf *var_name = &var_node->data.symbol_expr.symbol;
4574 var_node->block_context = child_context;4521 var_node->block_context = child_context;
4575 prong_node->data.switch_prong.var = add_local_var(g, var_node, child_context, var_name,4522 prong_node->data.switch_prong.var = add_local_var(g, var_node, import,
4576 var_type, true);4523 child_context, var_name, var_type, true);
4577 prong_node->data.switch_prong.var_is_target_expr = var_is_target_expr;4524 prong_node->data.switch_prong.var_is_target_expr = var_is_target_expr;
4578 }4525 }
45794526
...@@ -4598,6 +4545,9 @@ static TypeTableEntry *analyze_return_expr(CodeGen *g, ImportTableEntry *import,...@@ -4598,6 +4545,9 @@ static TypeTableEntry *analyze_return_expr(CodeGen *g, ImportTableEntry *import,
4598 normalize_parent_ptrs(node);4545 normalize_parent_ptrs(node);
4599 }4546 }
46004547
4548 // TODO follow the blocks to their parents, loop over all of them, set them all to true
4549 context->block_exit_paths[BlockExitPathReturn] = true;
4550
4601 TypeTableEntry *expected_return_type = get_return_type(context);4551 TypeTableEntry *expected_return_type = get_return_type(context);
46024552
4603 switch (node->data.return_expr.kind) {4553 switch (node->data.return_expr.kind) {
...@@ -4632,6 +4582,71 @@ static TypeTableEntry *analyze_return_expr(CodeGen *g, ImportTableEntry *import,...@@ -4632,6 +4582,71 @@ static TypeTableEntry *analyze_return_expr(CodeGen *g, ImportTableEntry *import,
4632 }4582 }
4633}4583}
46344584
4585static void validate_voided_expr(CodeGen *g, AstNode *source_node, TypeTableEntry *type_entry) {
4586 if (type_entry->id == TypeTableEntryIdMetaType) {
4587 add_node_error(g, first_executing_node(source_node), buf_sprintf("expected expression, found type"));
4588 } else if (type_entry->id == TypeTableEntryIdErrorUnion) {
4589 add_node_error(g, first_executing_node(source_node), buf_sprintf("statement ignores error value"));
4590 }
4591}
4592
4593static TypeTableEntry *analyze_defer_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
4594 TypeTableEntry *expected_type, AstNode *node)
4595{
4596 if (!context->fn_entry) {
4597 add_node_error(g, node, buf_sprintf("defer expression outside function definition"));
4598 return g->builtin_types.entry_invalid;
4599 }
4600
4601 if (!node->data.defer_expr.expr) {
4602 add_node_error(g, node, buf_sprintf("defer expects an expression"));
4603 return g->builtin_types.entry_void;
4604 }
4605
4606
4607 switch (node->data.defer_expr.kind) {
4608 case ReturnKindUnconditional:
4609 {
4610 TypeTableEntry *resolved_type = analyze_expression(g, import, context, nullptr,
4611 node->data.defer_expr.expr);
4612 validate_voided_expr(g, node->data.defer_expr.expr, resolved_type);
4613 zig_panic("TODO");
4614
4615 //node->data.defer_expr.index_in_block = context->defer_list.length;
4616 //context->defer_list.append(node);
4617 return g->builtin_types.entry_void;
4618 }
4619 case ReturnKindError:
4620 {
4621 TypeTableEntry *resolved_type = analyze_expression(g, import, context, nullptr,
4622 node->data.defer_expr.expr);
4623 if (resolved_type->id == TypeTableEntryIdInvalid) {
4624 // OK
4625 } else if (resolved_type->id == TypeTableEntryIdErrorUnion) {
4626 // OK
4627 } else {
4628 add_node_error(g, node->data.defer_expr.expr,
4629 buf_sprintf("expected error type, got '%s'", buf_ptr(&resolved_type->name)));
4630 }
4631 return g->builtin_types.entry_void;
4632 }
4633 case ReturnKindMaybe:
4634 {
4635 TypeTableEntry *resolved_type = analyze_expression(g, import, context, nullptr,
4636 node->data.defer_expr.expr);
4637 if (resolved_type->id == TypeTableEntryIdInvalid) {
4638 // OK
4639 } else if (resolved_type->id == TypeTableEntryIdMaybe) {
4640 // OK
4641 } else {
4642 add_node_error(g, node->data.defer_expr.expr,
4643 buf_sprintf("expected maybe type, got '%s'", buf_ptr(&resolved_type->name)));
4644 }
4645 return g->builtin_types.entry_void;
4646 }
4647 }
4648}
4649
4635static TypeTableEntry *analyze_string_literal_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,4650static TypeTableEntry *analyze_string_literal_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
4636 TypeTableEntry *expected_type, AstNode *node)4651 TypeTableEntry *expected_type, AstNode *node)
4637{4652{
...@@ -4652,10 +4667,8 @@ static TypeTableEntry *analyze_block_expr(CodeGen *g, ImportTableEntry *import,...@@ -4652,10 +4667,8 @@ static TypeTableEntry *analyze_block_expr(CodeGen *g, ImportTableEntry *import,
4652 for (int i = 0; i < node->data.block.statements.length; i += 1) {4667 for (int i = 0; i < node->data.block.statements.length; i += 1) {
4653 AstNode *child = node->data.block.statements.at(i);4668 AstNode *child = node->data.block.statements.at(i);
4654 if (child->type == NodeTypeLabel) {4669 if (child->type == NodeTypeLabel) {
4655 child->block_context = child_context;4670 add_node_error(g, child,
4656 LabelTableEntry *label_entry = child->data.label.label_entry;4671 buf_sprintf("label and goto not supported yet, see https://github.com/andrewrk/zig/issues/44"));
4657 assert(label_entry);
4658 label_entry->entered_from_fallthrough = (return_type->id != TypeTableEntryIdUnreachable);
4659 return_type = g->builtin_types.entry_void;4672 return_type = g->builtin_types.entry_void;
4660 continue;4673 continue;
4661 }4674 }
...@@ -4673,11 +4686,7 @@ static TypeTableEntry *analyze_block_expr(CodeGen *g, ImportTableEntry *import,...@@ -4673,11 +4686,7 @@ static TypeTableEntry *analyze_block_expr(CodeGen *g, ImportTableEntry *import,
4673 TypeTableEntry *passed_expected_type = is_last ? expected_type : nullptr;4686 TypeTableEntry *passed_expected_type = is_last ? expected_type : nullptr;
4674 return_type = analyze_expression(g, import, child_context, passed_expected_type, child);4687 return_type = analyze_expression(g, import, child_context, passed_expected_type, child);
4675 if (!is_last) {4688 if (!is_last) {
4676 if (return_type->id == TypeTableEntryIdMetaType) {4689 validate_voided_expr(g, child, return_type);
4677 add_node_error(g, child, buf_sprintf("expected expression, found type"));
4678 } else if (return_type->id == TypeTableEntryIdErrorUnion) {
4679 add_node_error(g, child, buf_sprintf("statement ignores error value"));
4680 }
4681 }4690 }
4682 }4691 }
4683 return return_type;4692 return return_type;
...@@ -4700,7 +4709,7 @@ static TypeTableEntry *analyze_asm_expr(CodeGen *g, ImportTableEntry *import, Bl...@@ -4700,7 +4709,7 @@ static TypeTableEntry *analyze_asm_expr(CodeGen *g, ImportTableEntry *import, Bl
4700 }4709 }
4701 } else {4710 } else {
4702 Buf *variable_name = &asm_output->variable_name;4711 Buf *variable_name = &asm_output->variable_name;
4703 VariableTableEntry *var = find_variable(context, variable_name);4712 VariableTableEntry *var = find_variable(context, variable_name, false);
4704 if (var) {4713 if (var) {
4705 asm_output->variable = var;4714 asm_output->variable = var;
4706 return var->type;4715 return var->type;
...@@ -4719,6 +4728,13 @@ static TypeTableEntry *analyze_asm_expr(CodeGen *g, ImportTableEntry *import, Bl...@@ -4719,6 +4728,13 @@ static TypeTableEntry *analyze_asm_expr(CodeGen *g, ImportTableEntry *import, Bl
4719 return return_type;4728 return return_type;
4720}4729}
47214730
4731static TypeTableEntry *analyze_goto(CodeGen *g, ImportTableEntry *import, BlockContext *context,
4732 TypeTableEntry *expected_type, AstNode *node)
4733{
4734 add_node_error(g, node, buf_sprintf("goto is broken, see https://github.com/andrewrk/zig/issues/44"));
4735 return g->builtin_types.entry_unreachable;
4736}
4737
4722// When you call analyze_expression, the node you pass might no longer be the child node4738// When you call analyze_expression, the node you pass might no longer be the child node
4723// you thought it was due to implicit casting rewriting the AST.4739// you thought it was due to implicit casting rewriting the AST.
4724static TypeTableEntry *analyze_expression(CodeGen *g, ImportTableEntry *import, BlockContext *context,4740static TypeTableEntry *analyze_expression(CodeGen *g, ImportTableEntry *import, BlockContext *context,
...@@ -4734,24 +4750,16 @@ static TypeTableEntry *analyze_expression(CodeGen *g, ImportTableEntry *import,...@@ -4734,24 +4750,16 @@ static TypeTableEntry *analyze_expression(CodeGen *g, ImportTableEntry *import,
4734 case NodeTypeReturnExpr:4750 case NodeTypeReturnExpr:
4735 return_type = analyze_return_expr(g, import, context, expected_type, node);4751 return_type = analyze_return_expr(g, import, context, expected_type, node);
4736 break;4752 break;
4753 case NodeTypeDeferExpr:
4754 return_type = analyze_defer_expr(g, import, context, expected_type, node);
4755 break;
4737 case NodeTypeVariableDeclaration:4756 case NodeTypeVariableDeclaration:
4738 analyze_variable_declaration(g, import, context, expected_type, node);4757 analyze_variable_declaration(g, import, context, expected_type, node);
4739 return_type = g->builtin_types.entry_void;4758 return_type = g->builtin_types.entry_void;
4740 break;4759 break;
4741 case NodeTypeGoto:4760 case NodeTypeGoto:
4742 {4761 analyze_goto(g, import, context, expected_type, node);
4743 FnTableEntry *fn_table_entry = get_context_fn_entry(context);4762 break;
4744 auto table_entry = fn_table_entry->label_table.maybe_get(&node->data.goto_expr.name);
4745 if (table_entry) {
4746 node->data.goto_expr.label_entry = table_entry->value;
4747 table_entry->value->used = true;
4748 } else {
4749 add_node_error(g, node,
4750 buf_sprintf("use of undeclared label '%s'", buf_ptr(&node->data.goto_expr.name)));
4751 }
4752 return_type = g->builtin_types.entry_unreachable;
4753 break;
4754 }
4755 case NodeTypeBreak:4763 case NodeTypeBreak:
4756 return_type = analyze_break_expr(g, import, context, expected_type, node);4764 return_type = analyze_break_expr(g, import, context, expected_type, node);
4757 break;4765 break;
...@@ -4909,7 +4917,7 @@ static void analyze_top_level_fn_def(CodeGen *g, ImportTableEntry *import, AstNo...@@ -4909,7 +4917,7 @@ static void analyze_top_level_fn_def(CodeGen *g, ImportTableEntry *import, AstNo
4909 add_node_error(g, param_decl_node, buf_sprintf("missing parameter name"));4917 add_node_error(g, param_decl_node, buf_sprintf("missing parameter name"));
4910 }4918 }
49114919
4912 VariableTableEntry *var = add_local_var(g, param_decl_node, context, &param_decl->name, type, true);4920 VariableTableEntry *var = add_local_var(g, param_decl_node, import, context, &param_decl->name, type, true);
4913 var->src_arg_index = i;4921 var->src_arg_index = i;
4914 param_decl_node->data.param_decl.variable = var;4922 param_decl_node->data.param_decl.variable = var;
49154923
...@@ -4920,22 +4928,6 @@ static void analyze_top_level_fn_def(CodeGen *g, ImportTableEntry *import, AstNo...@@ -4920,22 +4928,6 @@ static void analyze_top_level_fn_def(CodeGen *g, ImportTableEntry *import, AstNo
4920 TypeTableEntry *block_return_type = analyze_expression(g, import, context, expected_type, node->data.fn_def.body);4928 TypeTableEntry *block_return_type = analyze_expression(g, import, context, expected_type, node->data.fn_def.body);
49214929
4922 node->data.fn_def.implicit_return_type = block_return_type;4930 node->data.fn_def.implicit_return_type = block_return_type;
4923
4924 {
4925 auto it = fn_table_entry->label_table.entry_iterator();
4926 for (;;) {
4927 auto *entry = it.next();
4928 if (!entry)
4929 break;
4930
4931 LabelTableEntry *label_entry = entry->value;
4932 if (!label_entry->used) {
4933 add_node_error(g, label_entry->label_node,
4934 buf_sprintf("label '%s' defined but not used",
4935 buf_ptr(&label_entry->label_node->data.label.name)));
4936 }
4937 }
4938 }
4939}4931}
49404932
4941static void analyze_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode *node) {4933static void analyze_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode *node) {
...@@ -4964,6 +4956,7 @@ static void analyze_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode...@@ -4964,6 +4956,7 @@ static void analyze_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode
4964 case NodeTypeParamDecl:4956 case NodeTypeParamDecl:
4965 case NodeTypeFnDecl:4957 case NodeTypeFnDecl:
4966 case NodeTypeReturnExpr:4958 case NodeTypeReturnExpr:
4959 case NodeTypeDeferExpr:
4967 case NodeTypeRoot:4960 case NodeTypeRoot:
4968 case NodeTypeBlock:4961 case NodeTypeBlock:
4969 case NodeTypeBinOpExpr:4962 case NodeTypeBinOpExpr:
...@@ -5028,7 +5021,7 @@ static void collect_expr_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode...@@ -5028,7 +5021,7 @@ static void collect_expr_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode
5028 Buf *name = &node->data.symbol_expr.symbol;5021 Buf *name = &node->data.symbol_expr.symbol;
5029 auto table_entry = g->primitive_type_table.maybe_get(name);5022 auto table_entry = g->primitive_type_table.maybe_get(name);
5030 if (!table_entry) {5023 if (!table_entry) {
5031 table_entry = import->block_context->type_table.maybe_get(name);5024 table_entry = import->type_table.maybe_get(name);
5032 }5025 }
5033 if (!table_entry || !type_is_complete(table_entry->value)) {5026 if (!table_entry || !type_is_complete(table_entry->value)) {
5034 decl_node->deps.put(name, node);5027 decl_node->deps.put(name, node);
...@@ -5046,6 +5039,9 @@ static void collect_expr_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode...@@ -5046,6 +5039,9 @@ static void collect_expr_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode
5046 case NodeTypeReturnExpr:5039 case NodeTypeReturnExpr:
5047 collect_expr_decl_deps(g, import, node->data.return_expr.expr, decl_node);5040 collect_expr_decl_deps(g, import, node->data.return_expr.expr, decl_node);
5048 break;5041 break;
5042 case NodeTypeDeferExpr:
5043 collect_expr_decl_deps(g, import, node->data.defer_expr.expr, decl_node);
5044 break;
5049 case NodeTypePrefixOpExpr:5045 case NodeTypePrefixOpExpr:
5050 collect_expr_decl_deps(g, import, node->data.prefix_op_expr.primary_expr, decl_node);5046 collect_expr_decl_deps(g, import, node->data.prefix_op_expr.primary_expr, decl_node);
5051 break;5047 break;
...@@ -5196,7 +5192,7 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast...@@ -5196,7 +5192,7 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast
5196 Buf *name = &node->data.struct_decl.name;5192 Buf *name = &node->data.struct_decl.name;
5197 auto table_entry = g->primitive_type_table.maybe_get(name);5193 auto table_entry = g->primitive_type_table.maybe_get(name);
5198 if (!table_entry) {5194 if (!table_entry) {
5199 table_entry = import->block_context->type_table.maybe_get(name);5195 table_entry = import->type_table.maybe_get(name);
5200 }5196 }
5201 if (table_entry) {5197 if (table_entry) {
5202 node->data.struct_decl.type_entry = table_entry->value;5198 node->data.struct_decl.type_entry = table_entry->value;
...@@ -5210,20 +5206,20 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast...@@ -5210,20 +5206,20 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast
5210 node->data.struct_decl.kind, node, buf_ptr(name));5206 node->data.struct_decl.kind, node, buf_ptr(name));
5211 }5207 }
52125208
5213 import->block_context->type_table.put(&entry->name, entry);5209 import->type_table.put(&entry->name, entry);
5214 node->data.struct_decl.type_entry = entry;5210 node->data.struct_decl.type_entry = entry;
52155211
5216 bool is_pub = (node->data.struct_decl.visib_mod != VisibModPrivate);5212 bool is_pub = (node->data.struct_decl.visib_mod != VisibModPrivate);
5217 if (is_pub) {5213 if (is_pub) {
5218 for (int i = 0; i < import->importers.length; i += 1) {5214 for (int i = 0; i < import->importers.length; i += 1) {
5219 ImporterInfo importer = import->importers.at(i);5215 ImporterInfo importer = import->importers.at(i);
5220 auto table_entry = importer.import->block_context->type_table.maybe_get(&entry->name);5216 auto table_entry = importer.import->type_table.maybe_get(&entry->name);
5221 if (table_entry) {5217 if (table_entry) {
5222 add_node_error(g, importer.source_node,5218 add_node_error(g, importer.source_node,
5223 buf_sprintf("import of type '%s' overrides existing definition",5219 buf_sprintf("import of type '%s' overrides existing definition",
5224 buf_ptr(&entry->name)));5220 buf_ptr(&entry->name)));
5225 } else {5221 } else {
5226 importer.import->block_context->type_table.put(&entry->name, entry);5222 importer.import->type_table.put(&entry->name, entry);
5227 }5223 }
5228 }5224 }
5229 }5225 }
...@@ -5365,6 +5361,7 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast...@@ -5365,6 +5361,7 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast
5365 case NodeTypeParamDecl:5361 case NodeTypeParamDecl:
5366 case NodeTypeFnDecl:5362 case NodeTypeFnDecl:
5367 case NodeTypeReturnExpr:5363 case NodeTypeReturnExpr:
5364 case NodeTypeDeferExpr:
5368 case NodeTypeBlock:5365 case NodeTypeBlock:
5369 case NodeTypeBinOpExpr:5366 case NodeTypeBinOpExpr:
5370 case NodeTypeUnwrapErrorExpr:5367 case NodeTypeUnwrapErrorExpr:
...@@ -5555,6 +5552,8 @@ Expr *get_resolved_expr(AstNode *node) {...@@ -5555,6 +5552,8 @@ Expr *get_resolved_expr(AstNode *node) {
5555 switch (node->type) {5552 switch (node->type) {
5556 case NodeTypeReturnExpr:5553 case NodeTypeReturnExpr:
5557 return &node->data.return_expr.resolved_expr;5554 return &node->data.return_expr.resolved_expr;
5555 case NodeTypeDeferExpr:
5556 return &node->data.defer_expr.resolved_expr;
5558 case NodeTypeBinOpExpr:5557 case NodeTypeBinOpExpr:
5559 return &node->data.bin_op_expr.resolved_expr;5558 return &node->data.bin_op_expr.resolved_expr;
5560 case NodeTypeUnwrapErrorExpr:5559 case NodeTypeUnwrapErrorExpr:
...@@ -5653,6 +5652,7 @@ TopLevelDecl *get_resolved_top_level_decl(AstNode *node) {...@@ -5653,6 +5652,7 @@ TopLevelDecl *get_resolved_top_level_decl(AstNode *node) {
5653 return &node->data.type_decl.top_level_decl;5652 return &node->data.type_decl.top_level_decl;
5654 case NodeTypeNumberLiteral:5653 case NodeTypeNumberLiteral:
5655 case NodeTypeReturnExpr:5654 case NodeTypeReturnExpr:
5655 case NodeTypeDeferExpr:
5656 case NodeTypeBinOpExpr:5656 case NodeTypeBinOpExpr:
5657 case NodeTypeUnwrapErrorExpr:5657 case NodeTypeUnwrapErrorExpr:
5658 case NodeTypePrefixOpExpr:5658 case NodeTypePrefixOpExpr:
src/analyze.hpp-2
...@@ -14,8 +14,6 @@ void semantic_analyze(CodeGen *g);...@@ -14,8 +14,6 @@ void semantic_analyze(CodeGen *g);
14ErrorMsg *add_node_error(CodeGen *g, AstNode *node, Buf *msg);14ErrorMsg *add_node_error(CodeGen *g, AstNode *node, Buf *msg);
15TypeTableEntry *new_type_table_entry(TypeTableEntryId id);15TypeTableEntry *new_type_table_entry(TypeTableEntryId id);
16TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const);16TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const);
17VariableTableEntry *find_variable(BlockContext *context, Buf *name);
18TypeTableEntry *find_container(BlockContext *context, Buf *name);
19BlockContext *new_block_context(AstNode *node, BlockContext *parent);17BlockContext *new_block_context(AstNode *node, BlockContext *parent);
20Expr *get_resolved_expr(AstNode *node);18Expr *get_resolved_expr(AstNode *node);
21TopLevelDecl *get_resolved_top_level_decl(AstNode *node);19TopLevelDecl *get_resolved_top_level_decl(AstNode *node);
src/ast_render.cpp+12
...@@ -122,6 +122,8 @@ static const char *node_type_str(NodeType node_type) {...@@ -122,6 +122,8 @@ static const char *node_type_str(NodeType node_type) {
122 return "Directive";122 return "Directive";
123 case NodeTypeReturnExpr:123 case NodeTypeReturnExpr:
124 return "ReturnExpr";124 return "ReturnExpr";
125 case NodeTypeDeferExpr:
126 return "DeferExpr";
125 case NodeTypeVariableDeclaration:127 case NodeTypeVariableDeclaration:
126 return "VariableDeclaration";128 return "VariableDeclaration";
127 case NodeTypeTypeDecl:129 case NodeTypeTypeDecl:
...@@ -259,6 +261,14 @@ void ast_print(FILE *f, AstNode *node, int indent) {...@@ -259,6 +261,14 @@ void ast_print(FILE *f, AstNode *node, int indent) {
259 ast_print(f, node->data.return_expr.expr, indent + 2);261 ast_print(f, node->data.return_expr.expr, indent + 2);
260 break;262 break;
261 }263 }
264 case NodeTypeDeferExpr:
265 {
266 const char *prefix_str = return_prefix_str(node->data.defer_expr.kind);
267 fprintf(f, "%s%s\n", prefix_str, node_type_str(node->type));
268 if (node->data.defer_expr.expr)
269 ast_print(f, node->data.defer_expr.expr, indent + 2);
270 break;
271 }
262 case NodeTypeVariableDeclaration:272 case NodeTypeVariableDeclaration:
263 {273 {
264 Buf *name_buf = &node->data.variable_declaration.symbol;274 Buf *name_buf = &node->data.variable_declaration.symbol;
...@@ -620,6 +630,8 @@ static void render_node(AstRender *ar, AstNode *node) {...@@ -620,6 +630,8 @@ static void render_node(AstRender *ar, AstNode *node) {
620 break;630 break;
621 case NodeTypeReturnExpr:631 case NodeTypeReturnExpr:
622 zig_panic("TODO");632 zig_panic("TODO");
633 case NodeTypeDeferExpr:
634 zig_panic("TODO");
623 case NodeTypeVariableDeclaration:635 case NodeTypeVariableDeclaration:
624 {636 {
625 const char *pub_str = visib_mod_string(node->data.variable_declaration.visib_mod);637 const char *pub_str = visib_mod_string(node->data.variable_declaration.visib_mod);
src/codegen.cpp+79-74
...@@ -1669,6 +1669,15 @@ static LLVMValueRef gen_return_expr(CodeGen *g, AstNode *node) {...@@ -1669,6 +1669,15 @@ static LLVMValueRef gen_return_expr(CodeGen *g, AstNode *node) {
1669 }1669 }
1670}1670}
16711671
1672static LLVMValueRef gen_defer_expr(CodeGen *g, AstNode *node) {
1673 assert(node->type == NodeTypeDeferExpr);
1674
1675 zig_panic("TODO");
1676 //node->block_context->cur_defer_index = node->data.defer_expr.index_in_block;
1677
1678 return nullptr;
1679}
1680
1672static LLVMValueRef gen_if_bool_expr_raw(CodeGen *g, AstNode *source_node, LLVMValueRef cond_value,1681static LLVMValueRef gen_if_bool_expr_raw(CodeGen *g, AstNode *source_node, LLVMValueRef cond_value,
1673 AstNode *then_node, AstNode *else_node)1682 AstNode *then_node, AstNode *else_node)
1674{1683{
...@@ -1794,6 +1803,21 @@ static LLVMValueRef gen_if_var_expr(CodeGen *g, AstNode *node) {...@@ -1794,6 +1803,21 @@ static LLVMValueRef gen_if_var_expr(CodeGen *g, AstNode *node) {
1794static LLVMValueRef gen_block(CodeGen *g, AstNode *block_node, TypeTableEntry *implicit_return_type) {1803static LLVMValueRef gen_block(CodeGen *g, AstNode *block_node, TypeTableEntry *implicit_return_type) {
1795 assert(block_node->type == NodeTypeBlock);1804 assert(block_node->type == NodeTypeBlock);
17961805
1806 /* TODO
1807 BlockContext *block_context = block_node->data.block.block_context;
1808 if (block_context->defer_list.length > 0) {
1809 LLVMBasicBlockRef exit_scope_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "DeferExitScope");
1810
1811 for (int i = 0; i < block_context->defer_list.length; i += 1) {
1812 AstNode *defer_node = block_context->defer_list.at(i);
1813 defer_node->data.defer_expr.basic_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "DeferExpr");
1814 LLVMPositionBuilderAtEnd(g->builder, body_block);
1815 }
1816
1817 LLVMPositionBuilderAtEnd(g->builder, ?);
1818 }
1819 */
1820
1797 LLVMValueRef return_value;1821 LLVMValueRef return_value;
1798 for (int i = 0; i < block_node->data.block.statements.length; i += 1) {1822 for (int i = 0; i < block_node->data.block.statements.length; i += 1) {
1799 AstNode *statement_node = block_node->data.block.statements.at(i);1823 AstNode *statement_node = block_node->data.block.statements.at(i);
...@@ -2451,6 +2475,8 @@ static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) {...@@ -2451,6 +2475,8 @@ static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) {
2451 return gen_unwrap_err_expr(g, node);2475 return gen_unwrap_err_expr(g, node);
2452 case NodeTypeReturnExpr:2476 case NodeTypeReturnExpr:
2453 return gen_return_expr(g, node);2477 return gen_return_expr(g, node);
2478 case NodeTypeDeferExpr:
2479 return gen_defer_expr(g, node);
2454 case NodeTypeVariableDeclaration:2480 case NodeTypeVariableDeclaration:
2455 return gen_var_decl_expr(g, node);2481 return gen_var_decl_expr(g, node);
2456 case NodeTypePrefixOpExpr:2482 case NodeTypePrefixOpExpr:
...@@ -2478,24 +2504,13 @@ static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) {...@@ -2478,24 +2504,13 @@ static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) {
2478 case NodeTypeBlock:2504 case NodeTypeBlock:
2479 return gen_block(g, node, nullptr);2505 return gen_block(g, node, nullptr);
2480 case NodeTypeGoto:2506 case NodeTypeGoto:
2481 add_debug_source_node(g, node);2507 zig_unreachable();
2482 return LLVMBuildBr(g->builder, node->data.goto_expr.label_entry->basic_block);
2483 case NodeTypeBreak:2508 case NodeTypeBreak:
2484 return gen_break(g, node);2509 return gen_break(g, node);
2485 case NodeTypeContinue:2510 case NodeTypeContinue:
2486 return gen_continue(g, node);2511 return gen_continue(g, node);
2487 case NodeTypeLabel:2512 case NodeTypeLabel:
2488 {2513 zig_unreachable();
2489 LabelTableEntry *label_entry = node->data.label.label_entry;
2490 assert(label_entry);
2491 LLVMBasicBlockRef basic_block = label_entry->basic_block;
2492 if (label_entry->entered_from_fallthrough) {
2493 add_debug_source_node(g, node);
2494 LLVMBuildBr(g->builder, basic_block);
2495 }
2496 LLVMPositionBuilderAtEnd(g->builder, basic_block);
2497 return nullptr;
2498 }
2499 case NodeTypeContainerInitExpr:2514 case NodeTypeContainerInitExpr:
2500 return gen_container_init_expr(g, node);2515 return gen_container_init_expr(g, node);
2501 case NodeTypeSwitchExpr:2516 case NodeTypeSwitchExpr:
...@@ -2532,19 +2547,6 @@ static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) {...@@ -2532,19 +2547,6 @@ static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) {
2532 zig_unreachable();2547 zig_unreachable();
2533}2548}
25342549
2535static void build_label_blocks(CodeGen *g, AstNode *block_node) {
2536 assert(block_node->type == NodeTypeBlock);
2537 for (int i = 0; i < block_node->data.block.statements.length; i += 1) {
2538 AstNode *label_node = block_node->data.block.statements.at(i);
2539 if (label_node->type != NodeTypeLabel)
2540 continue;
2541
2542 Buf *name = &label_node->data.label.name;
2543 label_node->data.label.label_entry->basic_block = LLVMAppendBasicBlock(
2544 g->cur_fn->fn_value, buf_ptr(name));
2545 }
2546}
2547
2548static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *const_val) {2550static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *const_val) {
2549 assert(const_val->ok);2551 assert(const_val->ok);
25502552
...@@ -2977,11 +2979,7 @@ static void do_code_gen(CodeGen *g) {...@@ -2977,11 +2979,7 @@ static void do_code_gen(CodeGen *g) {
2977 LLVMPositionBuilderAtEnd(g->builder, entry_block);2979 LLVMPositionBuilderAtEnd(g->builder, entry_block);
29782980
29792981
2980 AstNode *body_node = fn_def_node->data.fn_def.body;2982 // Set up debug info for blocks
2981 build_label_blocks(g, body_node);
2982
2983 // Set up debug info for blocks and variables and
2984 // allocate all local variables
2985 for (int bc_i = 0; bc_i < fn_table_entry->all_block_contexts.length; bc_i += 1) {2983 for (int bc_i = 0; bc_i < fn_table_entry->all_block_contexts.length; bc_i += 1) {
2986 BlockContext *block_context = fn_table_entry->all_block_contexts.at(bc_i);2984 BlockContext *block_context = fn_table_entry->all_block_contexts.at(bc_i);
29872985
...@@ -2994,59 +2992,45 @@ static void do_code_gen(CodeGen *g) {...@@ -2994,59 +2992,45 @@ static void do_code_gen(CodeGen *g) {
2994 block_context->di_scope = LLVMZigLexicalBlockToScope(di_block);2992 block_context->di_scope = LLVMZigLexicalBlockToScope(di_block);
2995 }2993 }
29962994
2997 for (int var_i = 0; var_i < block_context->variable_list.length; var_i += 1) {
2998 VariableTableEntry *var = block_context->variable_list.at(var_i);
29992995
3000 if (!type_has_bits(var->type)) {2996 }
3001 continue;
3002 }
30032997
3004 unsigned tag;2998 // create debug variable declarations for variables and allocate all local variables
3005 unsigned arg_no;2999 for (int var_i = 0; var_i < fn_table_entry->variable_list.length; var_i += 1) {
3006 TypeTableEntry *gen_type;3000 VariableTableEntry *var = fn_table_entry->variable_list.at(var_i);
3007 if (block_context->node->type == NodeTypeFnDef) {
3008 tag = LLVMZigTag_DW_arg_variable();
3009 arg_no = var->gen_arg_index + 1;
30103001
3011 var->is_ptr = false;3002 if (!type_has_bits(var->type)) {
3012 assert(var->gen_arg_index >= 0);3003 continue;
3013 var->value_ref = LLVMGetParam(fn, var->gen_arg_index);3004 }
30143005
3015 gen_type = fn_table_entry->type_entry->data.fn.gen_param_info[var->src_arg_index].type;3006 unsigned tag;
3016 } else {3007 unsigned arg_no;
3017 tag = LLVMZigTag_DW_auto_variable();3008 TypeTableEntry *gen_type;
3018 arg_no = 0;3009 if (var->block_context->node->type == NodeTypeFnDef) {
3010 tag = LLVMZigTag_DW_arg_variable();
3011 arg_no = var->gen_arg_index + 1;
30193012
3020 add_debug_source_node(g, var->decl_node);3013 var->is_ptr = false;
3021 var->value_ref = LLVMBuildAlloca(g->builder, var->type->type_ref, buf_ptr(&var->name));3014 assert(var->gen_arg_index >= 0);
3022 uint64_t align_bytes = LLVMABISizeOfType(g->target_data_ref, var->type->type_ref);3015 var->value_ref = LLVMGetParam(fn, var->gen_arg_index);
3023 LLVMSetAlignment(var->value_ref, align_bytes);
30243016
3025 gen_type = var->type;3017 gen_type = fn_table_entry->type_entry->data.fn.gen_param_info[var->src_arg_index].type;
3026 }3018 } else {
3019 tag = LLVMZigTag_DW_auto_variable();
3020 arg_no = 0;
30273021
3028 var->di_loc_var = LLVMZigCreateLocalVariable(g->dbuilder, tag,3022 add_debug_source_node(g, var->decl_node);
3029 block_context->di_scope, buf_ptr(&var->name),3023 var->value_ref = LLVMBuildAlloca(g->builder, var->type->type_ref, buf_ptr(&var->name));
3030 import->di_file, var->decl_node->line + 1,3024 uint64_t align_bytes = LLVMABISizeOfType(g->target_data_ref, var->type->type_ref);
3031 gen_type->di_type, !g->strip_debug_symbols, 0, arg_no);3025 LLVMSetAlignment(var->value_ref, align_bytes);
3032 }
30333026
3034 // allocate structs which are the result of casts3027 gen_type = var->type;
3035 for (int cea_i = 0; cea_i < block_context->cast_alloca_list.length; cea_i += 1) {
3036 AstNode *fn_call_node = block_context->cast_alloca_list.at(cea_i);
3037 add_debug_source_node(g, fn_call_node);
3038 Expr *expr = &fn_call_node->data.fn_call_expr.resolved_expr;
3039 fn_call_node->data.fn_call_expr.tmp_ptr = LLVMBuildAlloca(g->builder,
3040 expr->type_entry->type_ref, "");
3041 }3028 }
30423029
3043 // allocate structs which are struct value expressions3030 var->di_loc_var = LLVMZigCreateLocalVariable(g->dbuilder, tag,
3044 for (int alloca_i = 0; alloca_i < block_context->struct_val_expr_alloca_list.length; alloca_i += 1) {3031 var->block_context->di_scope, buf_ptr(&var->name),
3045 StructValExprCodeGen *struct_val_expr_node = block_context->struct_val_expr_alloca_list.at(alloca_i);3032 import->di_file, var->decl_node->line + 1,
3046 add_debug_source_node(g, struct_val_expr_node->source_node);3033 gen_type->di_type, !g->strip_debug_symbols, 0, arg_no);
3047 struct_val_expr_node->ptr = LLVMBuildAlloca(g->builder,
3048 struct_val_expr_node->type_entry->type_ref, "");
3049 }
3050 }3034 }
30513035
3052 // create debug variable declarations for parameters3036 // create debug variable declarations for parameters
...@@ -3069,6 +3053,23 @@ static void do_code_gen(CodeGen *g) {...@@ -3069,6 +3053,23 @@ static void do_code_gen(CodeGen *g) {
3069 entry_block);3053 entry_block);
3070 }3054 }
30713055
3056 // allocate structs which are the result of casts
3057 for (int cea_i = 0; cea_i < fn_table_entry->cast_alloca_list.length; cea_i += 1) {
3058 AstNode *fn_call_node = fn_table_entry->cast_alloca_list.at(cea_i);
3059 add_debug_source_node(g, fn_call_node);
3060 Expr *expr = &fn_call_node->data.fn_call_expr.resolved_expr;
3061 fn_call_node->data.fn_call_expr.tmp_ptr = LLVMBuildAlloca(g->builder,
3062 expr->type_entry->type_ref, "");
3063 }
3064
3065 // allocate structs which are struct value expressions
3066 for (int alloca_i = 0; alloca_i < fn_table_entry->struct_val_expr_alloca_list.length; alloca_i += 1) {
3067 StructValExprCodeGen *struct_val_expr_node = fn_table_entry->struct_val_expr_alloca_list.at(alloca_i);
3068 add_debug_source_node(g, struct_val_expr_node->source_node);
3069 struct_val_expr_node->ptr = LLVMBuildAlloca(g->builder,
3070 struct_val_expr_node->type_entry->type_ref, "");
3071 }
3072
3072 TypeTableEntry *implicit_return_type = fn_def_node->data.fn_def.implicit_return_type;3073 TypeTableEntry *implicit_return_type = fn_def_node->data.fn_def.implicit_return_type;
3073 gen_block(g, fn_def_node->data.fn_def.body, implicit_return_type);3074 gen_block(g, fn_def_node->data.fn_def.body, implicit_return_type);
30743075
...@@ -3524,6 +3525,8 @@ void codegen_parseh(CodeGen *g, Buf *src_dirname, Buf *src_basename, Buf *source...@@ -3524,6 +3525,8 @@ void codegen_parseh(CodeGen *g, Buf *src_dirname, Buf *src_basename, Buf *source
3524 import->source_code = source_code;3525 import->source_code = source_code;
3525 import->path = full_path;3526 import->path = full_path;
3526 import->fn_table.init(32);3527 import->fn_table.init(32);
3528 import->type_table.init(8);
3529 import->error_table.init(8);
3527 g->root_import = import;3530 g->root_import = import;
35283531
3529 init(g, full_path);3532 init(g, full_path);
...@@ -3614,6 +3617,8 @@ static ImportTableEntry *codegen_add_code(CodeGen *g, Buf *abs_full_path,...@@ -3614,6 +3617,8 @@ static ImportTableEntry *codegen_add_code(CodeGen *g, Buf *abs_full_path,
3614 import_entry->line_offsets = tokenization.line_offsets;3617 import_entry->line_offsets = tokenization.line_offsets;
3615 import_entry->path = full_path;3618 import_entry->path = full_path;
3616 import_entry->fn_table.init(32);3619 import_entry->fn_table.init(32);
3620 import_entry->type_table.init(8);
3621 import_entry->error_table.init(8);
36173622
3618 import_entry->root = ast_parse(source_code, tokenization.tokens, import_entry, g->err_color,3623 import_entry->root = ast_parse(source_code, tokenization.tokens, import_entry, g->err_color,
3619 &g->next_node_index);3624 &g->next_node_index);
src/parser.cpp+23-12
...@@ -1635,20 +1635,24 @@ static AstNode *ast_parse_if_expr(ParseContext *pc, int *token_index, bool manda...@@ -1635,20 +1635,24 @@ static AstNode *ast_parse_if_expr(ParseContext *pc, int *token_index, bool manda
16351635
1636/*1636/*
1637ReturnExpression : option("%" | "?") "return" option(Expression)1637ReturnExpression : option("%" | "?") "return" option(Expression)
1638DeferExpression = option("%" | "?") "defer" option(Expression)
1638*/1639*/
1639static AstNode *ast_parse_return_expr(ParseContext *pc, int *token_index, bool mandatory) {1640static AstNode *ast_parse_return_or_defer_expr(ParseContext *pc, int *token_index) {
1640 Token *token = &pc->tokens->at(*token_index);1641 Token *token = &pc->tokens->at(*token_index);
16411642
1643 NodeType node_type;
1642 ReturnKind kind;1644 ReturnKind kind;
16431645
1644 if (token->id == TokenIdPercent) {1646 if (token->id == TokenIdPercent) {
1645 Token *next_token = &pc->tokens->at(*token_index + 1);1647 Token *next_token = &pc->tokens->at(*token_index + 1);
1646 if (next_token->id == TokenIdKeywordReturn) {1648 if (next_token->id == TokenIdKeywordReturn) {
1647 kind = ReturnKindError;1649 kind = ReturnKindError;
1650 node_type = NodeTypeReturnExpr;
1651 *token_index += 2;
1652 } else if (next_token->id == TokenIdKeywordDefer) {
1653 kind = ReturnKindError;
1654 node_type = NodeTypeDeferExpr;
1648 *token_index += 2;1655 *token_index += 2;
1649 } else if (mandatory) {
1650 ast_expect_token(pc, next_token, TokenIdKeywordReturn);
1651 zig_unreachable();
1652 } else {1656 } else {
1653 return nullptr;1657 return nullptr;
1654 }1658 }
...@@ -1656,24 +1660,28 @@ static AstNode *ast_parse_return_expr(ParseContext *pc, int *token_index, bool m...@@ -1656,24 +1660,28 @@ static AstNode *ast_parse_return_expr(ParseContext *pc, int *token_index, bool m
1656 Token *next_token = &pc->tokens->at(*token_index + 1);1660 Token *next_token = &pc->tokens->at(*token_index + 1);
1657 if (next_token->id == TokenIdKeywordReturn) {1661 if (next_token->id == TokenIdKeywordReturn) {
1658 kind = ReturnKindMaybe;1662 kind = ReturnKindMaybe;
1663 node_type = NodeTypeReturnExpr;
1664 *token_index += 2;
1665 } else if (next_token->id == TokenIdKeywordDefer) {
1666 kind = ReturnKindMaybe;
1667 node_type = NodeTypeDeferExpr;
1659 *token_index += 2;1668 *token_index += 2;
1660 } else if (mandatory) {
1661 ast_expect_token(pc, next_token, TokenIdKeywordReturn);
1662 zig_unreachable();
1663 } else {1669 } else {
1664 return nullptr;1670 return nullptr;
1665 }1671 }
1666 } else if (token->id == TokenIdKeywordReturn) {1672 } else if (token->id == TokenIdKeywordReturn) {
1667 kind = ReturnKindUnconditional;1673 kind = ReturnKindUnconditional;
1674 node_type = NodeTypeReturnExpr;
1675 *token_index += 1;
1676 } else if (token->id == TokenIdKeywordDefer) {
1677 kind = ReturnKindUnconditional;
1678 node_type = NodeTypeDeferExpr;
1668 *token_index += 1;1679 *token_index += 1;
1669 } else if (mandatory) {
1670 ast_expect_token(pc, token, TokenIdKeywordReturn);
1671 zig_unreachable();
1672 } else {1680 } else {
1673 return nullptr;1681 return nullptr;
1674 }1682 }
16751683
1676 AstNode *node = ast_create_node(pc, NodeTypeReturnExpr, token);1684 AstNode *node = ast_create_node(pc, node_type, token);
1677 node->data.return_expr.kind = kind;1685 node->data.return_expr.kind = kind;
1678 node->data.return_expr.expr = ast_parse_expression(pc, token_index, false);1686 node->data.return_expr.expr = ast_parse_expression(pc, token_index, false);
16791687
...@@ -2060,7 +2068,7 @@ NonBlockExpression : ReturnExpression | AssignmentExpression...@@ -2060,7 +2068,7 @@ NonBlockExpression : ReturnExpression | AssignmentExpression
2060static AstNode *ast_parse_non_block_expr(ParseContext *pc, int *token_index, bool mandatory) {2068static AstNode *ast_parse_non_block_expr(ParseContext *pc, int *token_index, bool mandatory) {
2061 Token *token = &pc->tokens->at(*token_index);2069 Token *token = &pc->tokens->at(*token_index);
20622070
2063 AstNode *return_expr = ast_parse_return_expr(pc, token_index, false);2071 AstNode *return_expr = ast_parse_return_or_defer_expr(pc, token_index);
2064 if (return_expr)2072 if (return_expr)
2065 return return_expr;2073 return return_expr;
20662074
...@@ -2695,6 +2703,9 @@ void normalize_parent_ptrs(AstNode *node) {...@@ -2695,6 +2703,9 @@ void normalize_parent_ptrs(AstNode *node) {
2695 case NodeTypeReturnExpr:2703 case NodeTypeReturnExpr:
2696 set_field(&node->data.return_expr.expr);2704 set_field(&node->data.return_expr.expr);
2697 break;2705 break;
2706 case NodeTypeDeferExpr:
2707 set_field(&node->data.defer_expr.expr);
2708 break;
2698 case NodeTypeVariableDeclaration:2709 case NodeTypeVariableDeclaration:
2699 set_list_fields(node->data.variable_declaration.directives);2710 set_list_fields(node->data.variable_declaration.directives);
2700 set_field(&node->data.variable_declaration.type);2711 set_field(&node->data.variable_declaration.type);
src/tokenizer.cpp+4
...@@ -102,6 +102,7 @@ const char * zig_keywords[] = {...@@ -102,6 +102,7 @@ const char * zig_keywords[] = {
102 "pub", "export", "import", "c_import", "if", "else", "goto", "asm",102 "pub", "export", "import", "c_import", "if", "else", "goto", "asm",
103 "volatile", "struct", "enum", "while", "for", "continue", "break",103 "volatile", "struct", "enum", "while", "for", "continue", "break",
104 "null", "noalias", "switch", "undefined", "error", "type", "inline",104 "null", "noalias", "switch", "undefined", "error", "type", "inline",
105 "defer",
105};106};
106107
107bool is_zig_keyword(Buf *buf) {108bool is_zig_keyword(Buf *buf) {
...@@ -275,6 +276,8 @@ static void end_token(Tokenize *t) {...@@ -275,6 +276,8 @@ static void end_token(Tokenize *t) {
275 t->cur_tok->id = TokenIdKeywordType;276 t->cur_tok->id = TokenIdKeywordType;
276 } else if (mem_eql_str(token_mem, token_len, "inline")) {277 } else if (mem_eql_str(token_mem, token_len, "inline")) {
277 t->cur_tok->id = TokenIdKeywordInline;278 t->cur_tok->id = TokenIdKeywordInline;
279 } else if (mem_eql_str(token_mem, token_len, "defer")) {
280 t->cur_tok->id = TokenIdKeywordDefer;
278 }281 }
279282
280 t->cur_tok = nullptr;283 t->cur_tok = nullptr;
...@@ -1090,6 +1093,7 @@ const char * token_name(TokenId id) {...@@ -1090,6 +1093,7 @@ const char * token_name(TokenId id) {
1090 case TokenIdKeywordError: return "error";1093 case TokenIdKeywordError: return "error";
1091 case TokenIdKeywordType: return "type";1094 case TokenIdKeywordType: return "type";
1092 case TokenIdKeywordInline: return "inline";1095 case TokenIdKeywordInline: return "inline";
1096 case TokenIdKeywordDefer: return "defer";
1093 case TokenIdLParen: return "(";1097 case TokenIdLParen: return "(";
1094 case TokenIdRParen: return ")";1098 case TokenIdRParen: return ")";
1095 case TokenIdComma: return ",";1099 case TokenIdComma: return ",";
src/tokenizer.hpp+1
...@@ -42,6 +42,7 @@ enum TokenId {...@@ -42,6 +42,7 @@ enum TokenId {
42 TokenIdKeywordError,42 TokenIdKeywordError,
43 TokenIdKeywordType,43 TokenIdKeywordType,
44 TokenIdKeywordInline,44 TokenIdKeywordInline,
45 TokenIdKeywordDefer,
45 TokenIdLParen,46 TokenIdLParen,
46 TokenIdRParen,47 TokenIdRParen,
47 TokenIdComma,48 TokenIdComma,
std/std.zig+2
...@@ -50,6 +50,8 @@ pub struct OutStream {...@@ -50,6 +50,8 @@ pub struct OutStream {
50 fd: isize,50 fd: isize,
51 buffer: [buffer_size]u8,51 buffer: [buffer_size]u8,
52 index: isize,52 index: isize,
53 // TODO remove this. let the user flush at will.
54 // for stderr the user can use printf
53 buffered: bool,55 buffered: bool,
5456
55 pub fn print_str(os: &OutStream, str: []const u8) -> %isize {57 pub fn print_str(os: &OutStream, str: []const u8) -> %isize {
test/run_tests.cpp-35
...@@ -259,25 +259,6 @@ pub fn main(args: [][]u8) -> %void {...@@ -259,25 +259,6 @@ pub fn main(args: [][]u8) -> %void {
259}259}
260 )SOURCE", "pass\n");260 )SOURCE", "pass\n");
261261
262 add_simple_case("goto", R"SOURCE(
263import "std.zig";
264
265fn loop(a : i32) {
266 if (a == 0) {
267 goto done;
268 }
269 %%stdout.printf("loop\n");
270 loop(a - 1);
271
272done:
273 return;
274}
275
276pub fn main(args: [][]u8) -> %void {
277 loop(3);
278}
279 )SOURCE", "loop\nloop\nloop\n");
280
281 add_simple_case("local variables", R"SOURCE(262 add_simple_case("local variables", R"SOURCE(
282import "std.zig";263import "std.zig";
283264
...@@ -1613,16 +1594,6 @@ fn a() {...@@ -1613,16 +1594,6 @@ fn a() {
1613 ".tmp_source.zig:3:5: error: use of undeclared identifier 'b'",1594 ".tmp_source.zig:3:5: error: use of undeclared identifier 'b'",
1614 ".tmp_source.zig:4:5: error: use of undeclared identifier 'c'");1595 ".tmp_source.zig:4:5: error: use of undeclared identifier 'c'");
16151596
1616 add_compile_fail_case("goto cause unreachable code", R"SOURCE(
1617fn a() {
1618 goto done;
1619 b();
1620done:
1621 return;
1622}
1623fn b() {}
1624 )SOURCE", 1, ".tmp_source.zig:4:5: error: unreachable code");
1625
1626 add_compile_fail_case("parameter redeclaration", R"SOURCE(1597 add_compile_fail_case("parameter redeclaration", R"SOURCE(
1627fn f(a : i32, a : i32) {1598fn f(a : i32, a : i32) {
1628}1599}
...@@ -1670,12 +1641,6 @@ fn f() {...@@ -1670,12 +1641,6 @@ fn f() {
1670fn f(a : unreachable) {}1641fn f(a : unreachable) {}
1671 )SOURCE", 1, ".tmp_source.zig:2:10: error: parameter of type 'unreachable' not allowed");1642 )SOURCE", 1, ".tmp_source.zig:2:10: error: parameter of type 'unreachable' not allowed");
16721643
1673 add_compile_fail_case("unused label", R"SOURCE(
1674fn f() {
1675a_label:
1676}
1677 )SOURCE", 1, ".tmp_source.zig:3:1: error: label 'a_label' defined but not used");
1678
1679 add_compile_fail_case("bad assignment target", R"SOURCE(1644 add_compile_fail_case("bad assignment target", R"SOURCE(
1680fn f() {1645fn f() {
1681 3 = 3;1646 3 = 3;