| author | |
| committer | |
| log | 9278dbedd5242bf4253da29c0fab36eea9dda61b |
| tree | 4bf997d327984a4772d7031de26949bc1b6e91c7 |
| parent | 18cfcfe44f4b4d624f20508210e2928396e3cf10 |
| parent | cd68969115f19b09aeb72923426e722725ba9451 |
8 files changed, 70 insertions(+), 21 deletions(-)
example/multiple_files/foo.zig+7-1| ... | @@ -1,5 +1,11 @@ | ... | @@ -1,5 +1,11 @@ |
| 1 | use "libc.zig"; | 1 | use "libc.zig"; |
| 2 | 2 | ||
| 3 | fn print_text() { | 3 | // purposefully conflicting function with main.zig |
| 4 | // but it's private so it should be OK | ||
| 5 | fn private_function() { | ||
| 4 | puts("it works!"); | 6 | puts("it works!"); |
| 5 | } | 7 | } |
| 8 | |||
| 9 | fn print_text() { | ||
| 10 | private_function(); | ||
| 11 | } |
example/multiple_files/main.zig+4| ... | @@ -4,6 +4,10 @@ use "libc.zig"; | ... | @@ -4,6 +4,10 @@ use "libc.zig"; |
| 4 | use "foo.zig"; | 4 | use "foo.zig"; |
| 5 | 5 | ||
| 6 | fn _start() -> unreachable { | 6 | fn _start() -> unreachable { |
| 7 | private_function(); | ||
| 8 | } | ||
| 9 | |||
| 10 | fn private_function() -> unreachable { | ||
| 7 | print_text(); | 11 | print_text(); |
| 8 | exit(0); | 12 | exit(0); |
| 9 | } | 13 | } |
src/analyze.cpp+20-5| ... | @@ -9,6 +9,7 @@ | ... | @@ -9,6 +9,7 @@ |
| 9 | #include "semantic_info.hpp" | 9 | #include "semantic_info.hpp" |
| 10 | #include "error.hpp" | 10 | #include "error.hpp" |
| 11 | #include "zig_llvm.hpp" | 11 | #include "zig_llvm.hpp" |
| 12 | #include "os.hpp" | ||
| 12 | 13 | ||
| 13 | struct BlockContext { | 14 | struct BlockContext { |
| 14 | AstNode *node; | 15 | AstNode *node; |
| ... | @@ -218,7 +219,7 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import, | ... | @@ -218,7 +219,7 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import, |
| 218 | } | 219 | } |
| 219 | break; | 220 | break; |
| 220 | case NodeTypeUse: | 221 | case NodeTypeUse: |
| 221 | zig_panic("TODO use"); | 222 | // nothing to do here |
| 222 | break; | 223 | break; |
| 223 | case NodeTypeDirective: | 224 | case NodeTypeDirective: |
| 224 | case NodeTypeParamDecl: | 225 | case NodeTypeParamDecl: |
| ... | @@ -545,9 +546,16 @@ static void analyze_top_level_declaration(CodeGen *g, AstNode *node) { | ... | @@ -545,9 +546,16 @@ static void analyze_top_level_declaration(CodeGen *g, AstNode *node) { |
| 545 | 546 | ||
| 546 | case NodeTypeRootExportDecl: | 547 | case NodeTypeRootExportDecl: |
| 547 | case NodeTypeExternBlock: | 548 | case NodeTypeExternBlock: |
| 548 | case NodeTypeUse: | ||
| 549 | // already looked at these in the preview pass | 549 | // already looked at these in the preview pass |
| 550 | break; | 550 | break; |
| 551 | case NodeTypeUse: | ||
| 552 | for (int i = 0; i < node->data.use.directives->length; i += 1) { | ||
| 553 | AstNode *directive_node = node->data.use.directives->at(i); | ||
| 554 | Buf *name = &directive_node->data.directive.name; | ||
| 555 | add_node_error(g, directive_node, | ||
| 556 | buf_sprintf("invalid directive: '%s'", buf_ptr(name))); | ||
| 557 | } | ||
| 558 | break; | ||
| 551 | case NodeTypeDirective: | 559 | case NodeTypeDirective: |
| 552 | case NodeTypeParamDecl: | 560 | case NodeTypeParamDecl: |
| 553 | case NodeTypeFnProto: | 561 | case NodeTypeFnProto: |
| ... | @@ -591,7 +599,14 @@ static void analyze_root(CodeGen *g, ImportTableEntry *import, AstNode *node) { | ... | @@ -591,7 +599,14 @@ static void analyze_root(CodeGen *g, ImportTableEntry *import, AstNode *node) { |
| 591 | } | 599 | } |
| 592 | } | 600 | } |
| 593 | 601 | ||
| 594 | void semantic_analyze(CodeGen *g, ImportTableEntry *import_table_entry) { | 602 | void semantic_analyze(CodeGen *g) { |
| 595 | analyze_root(g, import_table_entry, import_table_entry->root); | 603 | auto it = g->import_table.entry_iterator(); |
| 596 | } | 604 | for (;;) { |
| 605 | auto *entry = it.next(); | ||
| 606 | if (!entry) | ||
| 607 | break; | ||
| 597 | 608 | ||
| 609 | ImportTableEntry *import = entry->value; | ||
| 610 | analyze_root(g, import, import->root); | ||
| 611 | } | ||
| 612 | } |
src/analyze.hpp+1-2| ... | @@ -9,8 +9,7 @@ | ... | @@ -9,8 +9,7 @@ |
| 9 | #define ZIG_ANALYZE_HPP | 9 | #define ZIG_ANALYZE_HPP |
| 10 | 10 | ||
| 11 | struct CodeGen; | 11 | struct CodeGen; |
| 12 | struct ImportTableEntry; | ||
| 13 | 12 | ||
| 14 | void semantic_analyze(CodeGen *g, ImportTableEntry *entry); | 13 | void semantic_analyze(CodeGen *g); |
| 15 | 14 | ||
| 16 | #endif | 15 | #endif |
src/codegen.cpp+31-10| ... | @@ -664,12 +664,7 @@ static void init(CodeGen *g, Buf *source_path) { | ... | @@ -664,12 +664,7 @@ static void init(CodeGen *g, Buf *source_path) { |
| 664 | 664 | ||
| 665 | } | 665 | } |
| 666 | 666 | ||
| 667 | void codegen_add_code(CodeGen *g, Buf *source_path, Buf *source_code) { | 667 | static void codegen_add_code(CodeGen *g, Buf *source_path, Buf *source_code) { |
| 668 | if (!g->initialized) { | ||
| 669 | g->initialized = true; | ||
| 670 | init(g, source_path); | ||
| 671 | } | ||
| 672 | |||
| 673 | Buf full_path = BUF_INIT; | 668 | Buf full_path = BUF_INIT; |
| 674 | os_path_join(g->root_source_dir, source_path, &full_path); | 669 | os_path_join(g->root_source_dir, source_path, &full_path); |
| 675 | 670 | ||
| ... | @@ -696,20 +691,46 @@ void codegen_add_code(CodeGen *g, Buf *source_path, Buf *source_code) { | ... | @@ -696,20 +691,46 @@ void codegen_add_code(CodeGen *g, Buf *source_path, Buf *source_code) { |
| 696 | } | 691 | } |
| 697 | 692 | ||
| 698 | ImportTableEntry *import_entry = allocate<ImportTableEntry>(1); | 693 | ImportTableEntry *import_entry = allocate<ImportTableEntry>(1); |
| 694 | import_entry->fn_table.init(32); | ||
| 699 | import_entry->root = ast_parse(source_code, tokens); | 695 | import_entry->root = ast_parse(source_code, tokens); |
| 700 | assert(import_entry->root); | 696 | assert(import_entry->root); |
| 701 | if (g->verbose) { | 697 | if (g->verbose) { |
| 702 | ast_print(import_entry->root, 0); | 698 | ast_print(import_entry->root, 0); |
| 703 | |||
| 704 | fprintf(stderr, "\nSemantic Analysis:\n"); | ||
| 705 | fprintf(stderr, "--------------------\n"); | ||
| 706 | } | 699 | } |
| 707 | 700 | ||
| 708 | import_entry->path = source_path; | 701 | import_entry->path = source_path; |
| 709 | import_entry->di_file = LLVMZigCreateFile(g->dbuilder, buf_ptr(&basename), buf_ptr(&dirname)); | 702 | import_entry->di_file = LLVMZigCreateFile(g->dbuilder, buf_ptr(&basename), buf_ptr(&dirname)); |
| 710 | g->import_table.put(source_path, import_entry); | 703 | g->import_table.put(source_path, import_entry); |
| 711 | 704 | ||
| 712 | semantic_analyze(g, import_entry); | 705 | |
| 706 | assert(import_entry->root->type == NodeTypeRoot); | ||
| 707 | for (int decl_i = 0; decl_i < import_entry->root->data.root.top_level_decls.length; decl_i += 1) { | ||
| 708 | AstNode *top_level_decl = import_entry->root->data.root.top_level_decls.at(decl_i); | ||
| 709 | if (top_level_decl->type != NodeTypeUse) | ||
| 710 | continue; | ||
| 711 | |||
| 712 | auto entry = g->import_table.maybe_get(&top_level_decl->data.use.path); | ||
| 713 | if (!entry) { | ||
| 714 | Buf full_path = BUF_INIT; | ||
| 715 | os_path_join(g->root_source_dir, &top_level_decl->data.use.path, &full_path); | ||
| 716 | Buf import_code = BUF_INIT; | ||
| 717 | os_fetch_file_path(&full_path, &import_code); | ||
| 718 | codegen_add_code(g, &top_level_decl->data.use.path, &import_code); | ||
| 719 | } | ||
| 720 | } | ||
| 721 | } | ||
| 722 | |||
| 723 | void codegen_add_root_code(CodeGen *g, Buf *source_path, Buf *source_code) { | ||
| 724 | init(g, source_path); | ||
| 725 | |||
| 726 | codegen_add_code(g, source_path, source_code); | ||
| 727 | |||
| 728 | |||
| 729 | if (g->verbose) { | ||
| 730 | fprintf(stderr, "\nSemantic Analysis:\n"); | ||
| 731 | fprintf(stderr, "--------------------\n"); | ||
| 732 | } | ||
| 733 | semantic_analyze(g); | ||
| 713 | 734 | ||
| 714 | if (g->errors.length == 0) { | 735 | if (g->errors.length == 0) { |
| 715 | if (g->verbose) { | 736 | if (g->verbose) { |
src/codegen.hpp+1-1| ... | @@ -42,7 +42,7 @@ void codegen_set_verbose(CodeGen *codegen, bool verbose); | ... | @@ -42,7 +42,7 @@ void codegen_set_verbose(CodeGen *codegen, bool verbose); |
| 42 | void codegen_set_out_type(CodeGen *codegen, OutType out_type); | 42 | void codegen_set_out_type(CodeGen *codegen, OutType out_type); |
| 43 | void codegen_set_out_name(CodeGen *codegen, Buf *out_name); | 43 | void codegen_set_out_name(CodeGen *codegen, Buf *out_name); |
| 44 | 44 | ||
| 45 | void codegen_add_code(CodeGen *g, Buf *source_path, Buf *source_code); | 45 | void codegen_add_root_code(CodeGen *g, Buf *source_path, Buf *source_code); |
| 46 | 46 | ||
| 47 | void codegen_link(CodeGen *g, const char *out_file); | 47 | void codegen_link(CodeGen *g, const char *out_file); |
| 48 | 48 |
src/main.cpp+1-1| ... | @@ -73,7 +73,7 @@ static int build(const char *arg0, Build *b) { | ... | @@ -73,7 +73,7 @@ static int build(const char *arg0, Build *b) { |
| 73 | if (b->out_name) | 73 | if (b->out_name) |
| 74 | codegen_set_out_name(g, buf_create_from_str(b->out_name)); | 74 | codegen_set_out_name(g, buf_create_from_str(b->out_name)); |
| 75 | codegen_set_verbose(g, b->verbose); | 75 | codegen_set_verbose(g, b->verbose); |
| 76 | codegen_add_code(g, &root_source_name, &root_source_code); | 76 | codegen_add_root_code(g, &root_source_name, &root_source_code); |
| 77 | codegen_link(g, b->out_file); | 77 | codegen_link(g, b->out_file); |
| 78 | 78 | ||
| 79 | return 0; | 79 | return 0; |
src/semantic_info.hpp+5-1| ... | @@ -12,6 +12,8 @@ | ... | @@ -12,6 +12,8 @@ |
| 12 | #include "hash_map.hpp" | 12 | #include "hash_map.hpp" |
| 13 | #include "zig_llvm.hpp" | 13 | #include "zig_llvm.hpp" |
| 14 | 14 | ||
| 15 | struct FnTableEntry; | ||
| 16 | |||
| 15 | struct TypeTableEntry { | 17 | struct TypeTableEntry { |
| 16 | LLVMTypeRef type_ref; | 18 | LLVMTypeRef type_ref; |
| 17 | LLVMZigDIType *di_type; | 19 | LLVMZigDIType *di_type; |
| ... | @@ -28,6 +30,9 @@ struct ImportTableEntry { | ... | @@ -28,6 +30,9 @@ struct ImportTableEntry { |
| 28 | AstNode *root; | 30 | AstNode *root; |
| 29 | Buf *path; // relative to root_source_dir | 31 | Buf *path; // relative to root_source_dir |
| 30 | LLVMZigDIFile *di_file; | 32 | LLVMZigDIFile *di_file; |
| 33 | |||
| 34 | // reminder: hash tables must be initialized before use | ||
| 35 | HashMap<Buf *, FnTableEntry *, buf_hash, buf_eql_buf> fn_table; | ||
| 31 | }; | 36 | }; |
| 32 | 37 | ||
| 33 | struct FnTableEntry { | 38 | struct FnTableEntry { |
| ... | @@ -81,7 +86,6 @@ struct CodeGen { | ... | @@ -81,7 +86,6 @@ struct CodeGen { |
| 81 | int version_minor; | 86 | int version_minor; |
| 82 | int version_patch; | 87 | int version_patch; |
| 83 | bool verbose; | 88 | bool verbose; |
| 84 | bool initialized; | ||
| 85 | }; | 89 | }; |
| 86 | 90 | ||
| 87 | struct TypeNode { | 91 | struct TypeNode { |