| 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,7 +32,9 @@ zig | C equivalent | Description |
| 32 | ``` | 32 | ``` |
| 33 | Root : many(TopLevelDecl) token(EOF) | 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 | StructDecl : many(Directive) token(Struct) token(Symbol) token(LBrace) many(StructField) token(RBrace) | 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,6 +445,7 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import, |
| 445 | break; | 445 | break; |
| 446 | } | 446 | } |
| 447 | case NodeTypeUse: | 447 | case NodeTypeUse: |
| 448 | case NodeTypeVariableDeclaration: | ||
| 448 | // nothing to do here | 449 | // nothing to do here |
| 449 | break; | 450 | break; |
| 450 | case NodeTypeDirective: | 451 | case NodeTypeDirective: |
| ... | @@ -453,7 +454,6 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import, | ... | @@ -453,7 +454,6 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import, |
| 453 | case NodeTypeType: | 454 | case NodeTypeType: |
| 454 | case NodeTypeFnDecl: | 455 | case NodeTypeFnDecl: |
| 455 | case NodeTypeReturnExpr: | 456 | case NodeTypeReturnExpr: |
| 456 | case NodeTypeVariableDeclaration: | ||
| 457 | case NodeTypeRoot: | 457 | case NodeTypeRoot: |
| 458 | case NodeTypeBlock: | 458 | case NodeTypeBlock: |
| 459 | case NodeTypeBinOpExpr: | 459 | case NodeTypeBinOpExpr: |
| ... | @@ -505,6 +505,7 @@ static void preview_types(CodeGen *g, ImportTableEntry *import, AstNode *node) { | ... | @@ -505,6 +505,7 @@ static void preview_types(CodeGen *g, ImportTableEntry *import, AstNode *node) { |
| 505 | case NodeTypeFnDef: | 505 | case NodeTypeFnDef: |
| 506 | case NodeTypeRootExportDecl: | 506 | case NodeTypeRootExportDecl: |
| 507 | case NodeTypeUse: | 507 | case NodeTypeUse: |
| 508 | case NodeTypeVariableDeclaration: | ||
| 508 | // nothing to do | 509 | // nothing to do |
| 509 | break; | 510 | break; |
| 510 | case NodeTypeDirective: | 511 | case NodeTypeDirective: |
| ... | @@ -513,7 +514,6 @@ static void preview_types(CodeGen *g, ImportTableEntry *import, AstNode *node) { | ... | @@ -513,7 +514,6 @@ static void preview_types(CodeGen *g, ImportTableEntry *import, AstNode *node) { |
| 513 | case NodeTypeType: | 514 | case NodeTypeType: |
| 514 | case NodeTypeFnDecl: | 515 | case NodeTypeFnDecl: |
| 515 | case NodeTypeReturnExpr: | 516 | case NodeTypeReturnExpr: |
| 516 | case NodeTypeVariableDeclaration: | ||
| 517 | case NodeTypeRoot: | 517 | case NodeTypeRoot: |
| 518 | case NodeTypeBlock: | 518 | case NodeTypeBlock: |
| 519 | case NodeTypeBinOpExpr: | 519 | case NodeTypeBinOpExpr: |
| ... | @@ -537,26 +537,20 @@ static void preview_types(CodeGen *g, ImportTableEntry *import, AstNode *node) { | ... | @@ -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) { | 540 | static FnTableEntry *get_context_fn_entry(BlockContext *context) { |
| 541 | AstNode *fn_def_node = context->root->node; | 541 | assert(context->fn_entry); |
| 542 | assert(fn_def_node->type == NodeTypeFnDef); | 542 | return context->fn_entry; |
| 543 | AstNode *fn_proto_node = fn_def_node->data.fn_def.fn_proto; | 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 | assert(fn_proto_node->type == NodeTypeFnProto); | 548 | assert(fn_proto_node->type == NodeTypeFnProto); |
| 545 | AstNode *return_type_node = fn_proto_node->data.fn_proto.return_type; | 549 | AstNode *return_type_node = fn_proto_node->data.fn_proto.return_type; |
| 546 | assert(return_type_node->codegen_node); | 550 | assert(return_type_node->codegen_node); |
| 547 | return return_type_node->codegen_node->data.type_node.entry; | 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 | static void check_type_compatibility(CodeGen *g, AstNode *node, | 554 | static void check_type_compatibility(CodeGen *g, AstNode *node, |
| 561 | TypeTableEntry *expected_type, TypeTableEntry *actual_type) | 555 | TypeTableEntry *expected_type, TypeTableEntry *actual_type) |
| 562 | { | 556 | { |
| ... | @@ -575,21 +569,22 @@ static void check_type_compatibility(CodeGen *g, AstNode *node, | ... | @@ -575,21 +569,22 @@ static void check_type_compatibility(CodeGen *g, AstNode *node, |
| 575 | buf_ptr(&actual_type->name))); | 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 | BlockContext *context = allocate<BlockContext>(1); | 573 | BlockContext *context = allocate<BlockContext>(1); |
| 580 | context->node = node; | 574 | context->node = node; |
| 581 | context->parent = parent; | 575 | context->parent = parent; |
| 582 | if (parent != nullptr) | ||
| 583 | context->root = parent->root; | ||
| 584 | else | ||
| 585 | context->root = context; | ||
| 586 | context->variable_table.init(8); | 576 | context->variable_table.init(8); |
| 587 | 577 | ||
| 588 | AstNode *fn_def_node = context->root->node; | 578 | if (parent) { |
| 589 | assert(fn_def_node->type == NodeTypeFnDef); | 579 | context->fn_entry = parent->fn_entry; |
| 590 | assert(fn_def_node->codegen_node); | 580 | } else if (node && node->type == NodeTypeFnDef) { |
| 591 | FnDefNode *fn_def_info = &fn_def_node->codegen_node->data.fn_def_node; | 581 | AstNode *fn_proto_node = node->data.fn_def.fn_proto; |
| 592 | fn_def_info->all_block_contexts.append(context); | 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 | return context; | 589 | return context; |
| 595 | } | 590 | } |
| ... | @@ -1509,13 +1504,15 @@ static void analyze_top_level_declaration(CodeGen *g, ImportTableEntry *import, | ... | @@ -1509,13 +1504,15 @@ static void analyze_top_level_declaration(CodeGen *g, ImportTableEntry *import, |
| 1509 | case NodeTypeStructDecl: | 1504 | case NodeTypeStructDecl: |
| 1510 | // nothing to do | 1505 | // nothing to do |
| 1511 | break; | 1506 | break; |
| 1507 | case NodeTypeVariableDeclaration: | ||
| 1508 | analyze_variable_declaration(g, import, import->block_context, nullptr, node); | ||
| 1509 | break; | ||
| 1512 | case NodeTypeDirective: | 1510 | case NodeTypeDirective: |
| 1513 | case NodeTypeParamDecl: | 1511 | case NodeTypeParamDecl: |
| 1514 | case NodeTypeFnProto: | 1512 | case NodeTypeFnProto: |
| 1515 | case NodeTypeType: | 1513 | case NodeTypeType: |
| 1516 | case NodeTypeFnDecl: | 1514 | case NodeTypeFnDecl: |
| 1517 | case NodeTypeReturnExpr: | 1515 | case NodeTypeReturnExpr: |
| 1518 | case NodeTypeVariableDeclaration: | ||
| 1519 | case NodeTypeRoot: | 1516 | case NodeTypeRoot: |
| 1520 | case NodeTypeBlock: | 1517 | case NodeTypeBlock: |
| 1521 | case NodeTypeBinOpExpr: | 1518 | case NodeTypeBinOpExpr: |
src/analyze.hpp+7-5| ... | @@ -90,6 +90,7 @@ struct ImportTableEntry { | ... | @@ -90,6 +90,7 @@ struct ImportTableEntry { |
| 90 | LLVMZigDIFile *di_file; | 90 | LLVMZigDIFile *di_file; |
| 91 | Buf *source_code; | 91 | Buf *source_code; |
| 92 | ZigList<int> *line_offsets; | 92 | ZigList<int> *line_offsets; |
| 93 | BlockContext *block_context; | ||
| 93 | 94 | ||
| 94 | // reminder: hash tables must be initialized before use | 95 | // reminder: hash tables must be initialized before use |
| 95 | HashMap<Buf *, FnTableEntry *, buf_hash, buf_eql_buf> fn_table; | 96 | HashMap<Buf *, FnTableEntry *, buf_hash, buf_eql_buf> fn_table; |
| ... | @@ -116,6 +117,8 @@ struct FnTableEntry { | ... | @@ -116,6 +117,8 @@ struct FnTableEntry { |
| 116 | unsigned calling_convention; | 117 | unsigned calling_convention; |
| 117 | ImportTableEntry *import_entry; | 118 | ImportTableEntry *import_entry; |
| 118 | ZigList<FnAttrId> fn_attr_list; | 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 | // reminder: hash tables must be initialized before use | 123 | // reminder: hash tables must be initialized before use |
| 121 | HashMap<Buf *, LabelTableEntry *, buf_hash, buf_eql_buf> label_table; | 124 | HashMap<Buf *, LabelTableEntry *, buf_hash, buf_eql_buf> label_table; |
| ... | @@ -201,9 +204,9 @@ struct LocalVariableTableEntry { | ... | @@ -201,9 +204,9 @@ struct LocalVariableTableEntry { |
| 201 | }; | 204 | }; |
| 202 | 205 | ||
| 203 | struct BlockContext { | 206 | struct BlockContext { |
| 204 | AstNode *node; // either NodeTypeFnDef or NodeTypeBlock | 207 | AstNode *node; // either NodeTypeFnDef or NodeTypeBlock or null for module scope |
| 205 | BlockContext *root; // always points to the BlockContext with the NodeTypeFnDef | 208 | FnTableEntry *fn_entry; // null at the module scope |
| 206 | BlockContext *parent; // nullptr when this is the root | 209 | BlockContext *parent; // null when this is the root |
| 207 | HashMap<Buf *, LocalVariableTableEntry *, buf_hash, buf_eql_buf> variable_table; | 210 | HashMap<Buf *, LocalVariableTableEntry *, buf_hash, buf_eql_buf> variable_table; |
| 208 | ZigList<AstNode *> cast_expr_alloca_list; | 211 | ZigList<AstNode *> cast_expr_alloca_list; |
| 209 | LLVMZigDIScope *di_scope; | 212 | LLVMZigDIScope *di_scope; |
| ... | @@ -221,8 +224,6 @@ struct FnDefNode { | ... | @@ -221,8 +224,6 @@ struct FnDefNode { |
| 221 | TypeTableEntry *implicit_return_type; | 224 | TypeTableEntry *implicit_return_type; |
| 222 | BlockContext *block_context; | 225 | BlockContext *block_context; |
| 223 | bool skip; | 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 | struct ExprNode { | 229 | struct ExprNode { |
| ... | @@ -295,5 +296,6 @@ void add_node_error(CodeGen *g, AstNode *node, Buf *msg); | ... | @@ -295,5 +296,6 @@ void add_node_error(CodeGen *g, AstNode *node, Buf *msg); |
| 295 | TypeTableEntry *new_type_table_entry(TypeTableEntryId id); | 296 | TypeTableEntry *new_type_table_entry(TypeTableEntryId id); |
| 296 | TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const); | 297 | TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const); |
| 297 | LocalVariableTableEntry *find_local_variable(BlockContext *context, Buf *name); | 298 | LocalVariableTableEntry *find_local_variable(BlockContext *context, Buf *name); |
| 299 | BlockContext *new_block_context(AstNode *node, BlockContext *parent); | ||
| 298 | 300 | ||
| 299 | #endif | 301 | #endif |
src/codegen.cpp+5-2| ... | @@ -1132,8 +1132,8 @@ static void do_code_gen(CodeGen *g) { | ... | @@ -1132,8 +1132,8 @@ static void do_code_gen(CodeGen *g) { |
| 1132 | 1132 | ||
| 1133 | // Set up debug info for blocks and variables and | 1133 | // Set up debug info for blocks and variables and |
| 1134 | // allocate all local variables | 1134 | // allocate all local variables |
| 1135 | for (int bc_i = 0; bc_i < codegen_fn_def->all_block_contexts.length; bc_i += 1) { | 1135 | for (int bc_i = 0; bc_i < fn_table_entry->all_block_contexts.length; bc_i += 1) { |
| 1136 | BlockContext *block_context = codegen_fn_def->all_block_contexts.at(bc_i); | 1136 | BlockContext *block_context = fn_table_entry->all_block_contexts.at(bc_i); |
| 1137 | 1137 | ||
| 1138 | if (block_context->parent) { | 1138 | if (block_context->parent) { |
| 1139 | LLVMZigDILexicalBlock *di_block = LLVMZigCreateLexicalBlock(g->dbuilder, | 1139 | LLVMZigDILexicalBlock *di_block = LLVMZigCreateLexicalBlock(g->dbuilder, |
| ... | @@ -1530,6 +1530,9 @@ static ImportTableEntry *codegen_add_code(CodeGen *g, Buf *src_dirname, Buf *src | ... | @@ -1530,6 +1530,9 @@ static ImportTableEntry *codegen_add_code(CodeGen *g, Buf *src_dirname, Buf *src |
| 1530 | import_entry->di_file = LLVMZigCreateFile(g->dbuilder, buf_ptr(src_basename), buf_ptr(src_dirname)); | 1530 | import_entry->di_file = LLVMZigCreateFile(g->dbuilder, buf_ptr(src_basename), buf_ptr(src_dirname)); |
| 1531 | g->import_table.put(full_path, import_entry); | 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 | assert(import_entry->root->type == NodeTypeRoot); | 1537 | assert(import_entry->root->type == NodeTypeRoot); |
| 1535 | for (int decl_i = 0; decl_i < import_entry->root->data.root.top_level_decls.length; decl_i += 1) { | 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,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 | static void ast_parse_top_level_decls(ParseContext *pc, int *token_index, ZigList<AstNode *> *top_level_decls) { | 2271 | static void ast_parse_top_level_decls(ParseContext *pc, int *token_index, ZigList<AstNode *> *top_level_decls) { |
| 2272 | for (;;) { | 2272 | for (;;) { |
| ... | @@ -2310,6 +2310,13 @@ static void ast_parse_top_level_decls(ParseContext *pc, int *token_index, ZigLis | ... | @@ -2310,6 +2310,13 @@ static void ast_parse_top_level_decls(ParseContext *pc, int *token_index, ZigLis |
| 2310 | } | 2310 | } |
| 2311 | pc->directive_list = nullptr; | 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 | return; | 2320 | return; |
| 2314 | } | 2321 | } |
| 2315 | zig_unreachable(); | 2322 | zig_unreachable(); |