| author | |
| committer | |
| log | 52e19b4a9b6e6140bae3c20c6f1fef36dca20aa7 |
| tree | 7f08300bbaedd657fc46ae816e0302470becfb1a |
| parent | 304941026013e6310c9362849610c32d98d1332a |
5 files changed, 47 insertions(+), 36 deletions(-)
doc/langref.md+3-1| ... | ... | @@ -32,7 +32,9 @@ zig | C equivalent | Description |
| 32 | 32 | ``` |
| 33 | 33 | Root : many(TopLevelDecl) token(EOF) |
| 34 | 34 | |
| 35 | TopLevelDecl : FnDef | ExternBlock | RootExportDecl | Use | StructDecl | |
| 35 | TopLevelDecl : FnDef | ExternBlock | RootExportDecl | Use | StructDecl | VariableDeclaration | |
| 36 | ||
| 37 | VariableDeclaration : (token(Var) | token(Const)) token(Symbol) (token(Eq) Expression | token(Colon) Type option(token(Eq) Expression)) | |
| 36 | 38 | |
| 37 | 39 | StructDecl : many(Directive) token(Struct) token(Symbol) token(LBrace) many(StructField) token(RBrace) |
| 38 | 40 |
src/analyze.cpp+24-27| ... | ... | @@ -445,6 +445,7 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import, |
| 445 | 445 | break; |
| 446 | 446 | } |
| 447 | 447 | case NodeTypeUse: |
| 448 | case NodeTypeVariableDeclaration: | |
| 448 | 449 | // nothing to do here |
| 449 | 450 | break; |
| 450 | 451 | case NodeTypeDirective: |
| ... | ... | @@ -453,7 +454,6 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import, |
| 453 | 454 | case NodeTypeType: |
| 454 | 455 | case NodeTypeFnDecl: |
| 455 | 456 | case NodeTypeReturnExpr: |
| 456 | case NodeTypeVariableDeclaration: | |
| 457 | 457 | case NodeTypeRoot: |
| 458 | 458 | case NodeTypeBlock: |
| 459 | 459 | case NodeTypeBinOpExpr: |
| ... | ... | @@ -505,6 +505,7 @@ static void preview_types(CodeGen *g, ImportTableEntry *import, AstNode *node) { |
| 505 | 505 | case NodeTypeFnDef: |
| 506 | 506 | case NodeTypeRootExportDecl: |
| 507 | 507 | case NodeTypeUse: |
| 508 | case NodeTypeVariableDeclaration: | |
| 508 | 509 | // nothing to do |
| 509 | 510 | break; |
| 510 | 511 | case NodeTypeDirective: |
| ... | ... | @@ -513,7 +514,6 @@ static void preview_types(CodeGen *g, ImportTableEntry *import, AstNode *node) { |
| 513 | 514 | case NodeTypeType: |
| 514 | 515 | case NodeTypeFnDecl: |
| 515 | 516 | case NodeTypeReturnExpr: |
| 516 | case NodeTypeVariableDeclaration: | |
| 517 | 517 | case NodeTypeRoot: |
| 518 | 518 | case NodeTypeBlock: |
| 519 | 519 | case NodeTypeBinOpExpr: |
| ... | ... | @@ -537,26 +537,20 @@ static void preview_types(CodeGen *g, ImportTableEntry *import, AstNode *node) { |
| 537 | 537 | } |
| 538 | 538 | } |
| 539 | 539 | |
| 540 | static TypeTableEntry * get_return_type(BlockContext *context) { | |
| 541 | AstNode *fn_def_node = context->root->node; | |
| 542 | assert(fn_def_node->type == NodeTypeFnDef); | |
| 543 | AstNode *fn_proto_node = fn_def_node->data.fn_def.fn_proto; | |
| 540 | static FnTableEntry *get_context_fn_entry(BlockContext *context) { | |
| 541 | assert(context->fn_entry); | |
| 542 | return context->fn_entry; | |
| 543 | } | |
| 544 | ||
| 545 | static TypeTableEntry *get_return_type(BlockContext *context) { | |
| 546 | FnTableEntry *fn_entry = get_context_fn_entry(context); | |
| 547 | AstNode *fn_proto_node = fn_entry->proto_node; | |
| 544 | 548 | assert(fn_proto_node->type == NodeTypeFnProto); |
| 545 | 549 | AstNode *return_type_node = fn_proto_node->data.fn_proto.return_type; |
| 546 | 550 | assert(return_type_node->codegen_node); |
| 547 | 551 | return return_type_node->codegen_node->data.type_node.entry; |
| 548 | 552 | } |
| 549 | 553 | |
| 550 | static FnTableEntry *get_context_fn_entry(BlockContext *context) { | |
| 551 | AstNode *fn_def_node = context->root->node; | |
| 552 | assert(fn_def_node->type == NodeTypeFnDef); | |
| 553 | AstNode *fn_proto_node = fn_def_node->data.fn_def.fn_proto; | |
| 554 | assert(fn_proto_node->type == NodeTypeFnProto); | |
| 555 | assert(fn_proto_node->codegen_node); | |
| 556 | assert(fn_proto_node->codegen_node->data.fn_proto_node.fn_table_entry); | |
| 557 | return fn_proto_node->codegen_node->data.fn_proto_node.fn_table_entry; | |
| 558 | } | |
| 559 | ||
| 560 | 554 | static void check_type_compatibility(CodeGen *g, AstNode *node, |
| 561 | 555 | TypeTableEntry *expected_type, TypeTableEntry *actual_type) |
| 562 | 556 | { |
| ... | ... | @@ -575,21 +569,22 @@ static void check_type_compatibility(CodeGen *g, AstNode *node, |
| 575 | 569 | buf_ptr(&actual_type->name))); |
| 576 | 570 | } |
| 577 | 571 | |
| 578 | static BlockContext *new_block_context(AstNode *node, BlockContext *parent) { | |
| 572 | BlockContext *new_block_context(AstNode *node, BlockContext *parent) { | |
| 579 | 573 | BlockContext *context = allocate<BlockContext>(1); |
| 580 | 574 | context->node = node; |
| 581 | 575 | context->parent = parent; |
| 582 | if (parent != nullptr) | |
| 583 | context->root = parent->root; | |
| 584 | else | |
| 585 | context->root = context; | |
| 586 | 576 | context->variable_table.init(8); |
| 587 | 577 | |
| 588 | AstNode *fn_def_node = context->root->node; | |
| 589 | assert(fn_def_node->type == NodeTypeFnDef); | |
| 590 | assert(fn_def_node->codegen_node); | |
| 591 | FnDefNode *fn_def_info = &fn_def_node->codegen_node->data.fn_def_node; | |
| 592 | fn_def_info->all_block_contexts.append(context); | |
| 578 | if (parent) { | |
| 579 | context->fn_entry = parent->fn_entry; | |
| 580 | } else if (node && node->type == NodeTypeFnDef) { | |
| 581 | AstNode *fn_proto_node = node->data.fn_def.fn_proto; | |
| 582 | context->fn_entry = fn_proto_node->codegen_node->data.fn_proto_node.fn_table_entry; | |
| 583 | } | |
| 584 | ||
| 585 | if (context->fn_entry) { | |
| 586 | context->fn_entry->all_block_contexts.append(context); | |
| 587 | } | |
| 593 | 588 | |
| 594 | 589 | return context; |
| 595 | 590 | } |
| ... | ... | @@ -1509,13 +1504,15 @@ static void analyze_top_level_declaration(CodeGen *g, ImportTableEntry *import, |
| 1509 | 1504 | case NodeTypeStructDecl: |
| 1510 | 1505 | // nothing to do |
| 1511 | 1506 | break; |
| 1507 | case NodeTypeVariableDeclaration: | |
| 1508 | analyze_variable_declaration(g, import, import->block_context, nullptr, node); | |
| 1509 | break; | |
| 1512 | 1510 | case NodeTypeDirective: |
| 1513 | 1511 | case NodeTypeParamDecl: |
| 1514 | 1512 | case NodeTypeFnProto: |
| 1515 | 1513 | case NodeTypeType: |
| 1516 | 1514 | case NodeTypeFnDecl: |
| 1517 | 1515 | case NodeTypeReturnExpr: |
| 1518 | case NodeTypeVariableDeclaration: | |
| 1519 | 1516 | case NodeTypeRoot: |
| 1520 | 1517 | case NodeTypeBlock: |
| 1521 | 1518 | case NodeTypeBinOpExpr: |
src/analyze.hpp+7-5| ... | ... | @@ -90,6 +90,7 @@ struct ImportTableEntry { |
| 90 | 90 | LLVMZigDIFile *di_file; |
| 91 | 91 | Buf *source_code; |
| 92 | 92 | ZigList<int> *line_offsets; |
| 93 | BlockContext *block_context; | |
| 93 | 94 | |
| 94 | 95 | // reminder: hash tables must be initialized before use |
| 95 | 96 | HashMap<Buf *, FnTableEntry *, buf_hash, buf_eql_buf> fn_table; |
| ... | ... | @@ -116,6 +117,8 @@ struct FnTableEntry { |
| 116 | 117 | unsigned calling_convention; |
| 117 | 118 | ImportTableEntry *import_entry; |
| 118 | 119 | ZigList<FnAttrId> fn_attr_list; |
| 120 | // Required to be a pre-order traversal of the AST. (parents must come before children) | |
| 121 | ZigList<BlockContext *> all_block_contexts; | |
| 119 | 122 | |
| 120 | 123 | // reminder: hash tables must be initialized before use |
| 121 | 124 | HashMap<Buf *, LabelTableEntry *, buf_hash, buf_eql_buf> label_table; |
| ... | ... | @@ -201,9 +204,9 @@ struct LocalVariableTableEntry { |
| 201 | 204 | }; |
| 202 | 205 | |
| 203 | 206 | struct BlockContext { |
| 204 | AstNode *node; // either NodeTypeFnDef or NodeTypeBlock | |
| 205 | BlockContext *root; // always points to the BlockContext with the NodeTypeFnDef | |
| 206 | BlockContext *parent; // nullptr when this is the root | |
| 207 | AstNode *node; // either NodeTypeFnDef or NodeTypeBlock or null for module scope | |
| 208 | FnTableEntry *fn_entry; // null at the module scope | |
| 209 | BlockContext *parent; // null when this is the root | |
| 207 | 210 | HashMap<Buf *, LocalVariableTableEntry *, buf_hash, buf_eql_buf> variable_table; |
| 208 | 211 | ZigList<AstNode *> cast_expr_alloca_list; |
| 209 | 212 | LLVMZigDIScope *di_scope; |
| ... | ... | @@ -221,8 +224,6 @@ struct FnDefNode { |
| 221 | 224 | TypeTableEntry *implicit_return_type; |
| 222 | 225 | BlockContext *block_context; |
| 223 | 226 | bool skip; |
| 224 | // Required to be a pre-order traversal of the AST. (parents must come before children) | |
| 225 | ZigList<BlockContext *> all_block_contexts; | |
| 226 | 227 | }; |
| 227 | 228 | |
| 228 | 229 | struct ExprNode { |
| ... | ... | @@ -295,5 +296,6 @@ void add_node_error(CodeGen *g, AstNode *node, Buf *msg); |
| 295 | 296 | TypeTableEntry *new_type_table_entry(TypeTableEntryId id); |
| 296 | 297 | TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const); |
| 297 | 298 | LocalVariableTableEntry *find_local_variable(BlockContext *context, Buf *name); |
| 299 | BlockContext *new_block_context(AstNode *node, BlockContext *parent); | |
| 298 | 300 | |
| 299 | 301 | #endif |
src/codegen.cpp+5-2| ... | ... | @@ -1132,8 +1132,8 @@ static void do_code_gen(CodeGen *g) { |
| 1132 | 1132 | |
| 1133 | 1133 | // Set up debug info for blocks and variables and |
| 1134 | 1134 | // allocate all local variables |
| 1135 | for (int bc_i = 0; bc_i < codegen_fn_def->all_block_contexts.length; bc_i += 1) { | |
| 1136 | BlockContext *block_context = codegen_fn_def->all_block_contexts.at(bc_i); | |
| 1135 | for (int bc_i = 0; bc_i < fn_table_entry->all_block_contexts.length; bc_i += 1) { | |
| 1136 | BlockContext *block_context = fn_table_entry->all_block_contexts.at(bc_i); | |
| 1137 | 1137 | |
| 1138 | 1138 | if (block_context->parent) { |
| 1139 | 1139 | LLVMZigDILexicalBlock *di_block = LLVMZigCreateLexicalBlock(g->dbuilder, |
| ... | ... | @@ -1530,6 +1530,9 @@ static ImportTableEntry *codegen_add_code(CodeGen *g, Buf *src_dirname, Buf *src |
| 1530 | 1530 | import_entry->di_file = LLVMZigCreateFile(g->dbuilder, buf_ptr(src_basename), buf_ptr(src_dirname)); |
| 1531 | 1531 | g->import_table.put(full_path, import_entry); |
| 1532 | 1532 | |
| 1533 | import_entry->block_context = new_block_context(nullptr, nullptr); | |
| 1534 | import_entry->block_context->di_scope = LLVMZigFileToScope(import_entry->di_file); | |
| 1535 | ||
| 1533 | 1536 | |
| 1534 | 1537 | assert(import_entry->root->type == NodeTypeRoot); |
| 1535 | 1538 | for (int decl_i = 0; decl_i < import_entry->root->data.root.top_level_decls.length; decl_i += 1) { |
src/parser.cpp+8-1| ... | ... | @@ -2266,7 +2266,7 @@ static AstNode *ast_parse_struct_decl(ParseContext *pc, int *token_index) { |
| 2266 | 2266 | } |
| 2267 | 2267 | |
| 2268 | 2268 | /* |
| 2269 | TopLevelDecl : FnDef | ExternBlock | RootExportDecl | Use | StructDecl | |
| 2269 | TopLevelDecl : FnDef | ExternBlock | RootExportDecl | Use | StructDecl | VariableDeclaration | |
| 2270 | 2270 | */ |
| 2271 | 2271 | static void ast_parse_top_level_decls(ParseContext *pc, int *token_index, ZigList<AstNode *> *top_level_decls) { |
| 2272 | 2272 | for (;;) { |
| ... | ... | @@ -2310,6 +2310,13 @@ static void ast_parse_top_level_decls(ParseContext *pc, int *token_index, ZigLis |
| 2310 | 2310 | } |
| 2311 | 2311 | pc->directive_list = nullptr; |
| 2312 | 2312 | |
| 2313 | AstNode *var_decl_node = ast_parse_variable_declaration_expr(pc, token_index, false); | |
| 2314 | if (var_decl_node) { | |
| 2315 | ast_eat_token(pc, token_index, TokenIdSemicolon); | |
| 2316 | top_level_decls->append(var_decl_node); | |
| 2317 | continue; | |
| 2318 | } | |
| 2319 | ||
| 2313 | 2320 | return; |
| 2314 | 2321 | } |
| 2315 | 2322 | zig_unreachable(); |