| author | |
| committer | |
| log | cd68969115f19b09aeb72923426e722725ba9451 |
| tree | 291d34566589752492f1d3ac9b63aa78e72dcd39 |
| parent | 55b8472374eede496b59396dbe253b05b16063e1 |
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 | static void add_node_error(CodeGen *g, AstNode *node, Buf *msg) { | 14 | static void add_node_error(CodeGen *g, AstNode *node, Buf *msg) { |
| 14 | g->errors.add_one(); | 15 | g->errors.add_one(); |
| ... | @@ -212,7 +213,7 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import, | ... | @@ -212,7 +213,7 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import, |
| 212 | } | 213 | } |
| 213 | break; | 214 | break; |
| 214 | case NodeTypeUse: | 215 | case NodeTypeUse: |
| 215 | zig_panic("TODO use"); | 216 | // nothing to do here |
| 216 | break; | 217 | break; |
| 217 | case NodeTypeDirective: | 218 | case NodeTypeDirective: |
| 218 | case NodeTypeParamDecl: | 219 | case NodeTypeParamDecl: |
| ... | @@ -383,9 +384,16 @@ static void analyze_top_level_declaration(CodeGen *g, AstNode *node) { | ... | @@ -383,9 +384,16 @@ static void analyze_top_level_declaration(CodeGen *g, AstNode *node) { |
| 383 | 384 | ||
| 384 | case NodeTypeRootExportDecl: | 385 | case NodeTypeRootExportDecl: |
| 385 | case NodeTypeExternBlock: | 386 | case NodeTypeExternBlock: |
| 386 | case NodeTypeUse: | ||
| 387 | // already looked at these in the preview pass | 387 | // already looked at these in the preview pass |
| 388 | break; | 388 | break; |
| 389 | case NodeTypeUse: | ||
| 390 | for (int i = 0; i < node->data.use.directives->length; i += 1) { | ||
| 391 | AstNode *directive_node = node->data.use.directives->at(i); | ||
| 392 | Buf *name = &directive_node->data.directive.name; | ||
| 393 | add_node_error(g, directive_node, | ||
| 394 | buf_sprintf("invalid directive: '%s'", buf_ptr(name))); | ||
| 395 | } | ||
| 396 | break; | ||
| 389 | case NodeTypeDirective: | 397 | case NodeTypeDirective: |
| 390 | case NodeTypeParamDecl: | 398 | case NodeTypeParamDecl: |
| 391 | case NodeTypeFnProto: | 399 | case NodeTypeFnProto: |
| ... | @@ -429,7 +437,14 @@ static void analyze_root(CodeGen *g, ImportTableEntry *import, AstNode *node) { | ... | @@ -429,7 +437,14 @@ static void analyze_root(CodeGen *g, ImportTableEntry *import, AstNode *node) { |
| 429 | } | 437 | } |
| 430 | } | 438 | } |
| 431 | 439 | ||
| 432 | void semantic_analyze(CodeGen *g, ImportTableEntry *import_table_entry) { | 440 | void semantic_analyze(CodeGen *g) { |
| 433 | analyze_root(g, import_table_entry, import_table_entry->root); | 441 | auto it = g->import_table.entry_iterator(); |
| 434 | } | 442 | for (;;) { |
| 443 | auto *entry = it.next(); | ||
| 444 | if (!entry) | ||
| 445 | break; | ||
| 435 | 446 | ||
| 447 | ImportTableEntry *import = entry->value; | ||
| 448 | analyze_root(g, import, import->root); | ||
| 449 | } | ||
| 450 | } |
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| ... | @@ -661,12 +661,7 @@ static void init(CodeGen *g, Buf *source_path) { | ... | @@ -661,12 +661,7 @@ static void init(CodeGen *g, Buf *source_path) { |
| 661 | 661 | ||
| 662 | } | 662 | } |
| 663 | 663 | ||
| 664 | void codegen_add_code(CodeGen *g, Buf *source_path, Buf *source_code) { | 664 | static void codegen_add_code(CodeGen *g, Buf *source_path, Buf *source_code) { |
| 665 | if (!g->initialized) { | ||
| 666 | g->initialized = true; | ||
| 667 | init(g, source_path); | ||
| 668 | } | ||
| 669 | |||
| 670 | Buf full_path = BUF_INIT; | 665 | Buf full_path = BUF_INIT; |
| 671 | os_path_join(g->root_source_dir, source_path, &full_path); | 666 | os_path_join(g->root_source_dir, source_path, &full_path); |
| 672 | 667 | ||
| ... | @@ -693,20 +688,46 @@ void codegen_add_code(CodeGen *g, Buf *source_path, Buf *source_code) { | ... | @@ -693,20 +688,46 @@ void codegen_add_code(CodeGen *g, Buf *source_path, Buf *source_code) { |
| 693 | } | 688 | } |
| 694 | 689 | ||
| 695 | ImportTableEntry *import_entry = allocate<ImportTableEntry>(1); | 690 | ImportTableEntry *import_entry = allocate<ImportTableEntry>(1); |
| 691 | import_entry->fn_table.init(32); | ||
| 696 | import_entry->root = ast_parse(source_code, tokens); | 692 | import_entry->root = ast_parse(source_code, tokens); |
| 697 | assert(import_entry->root); | 693 | assert(import_entry->root); |
| 698 | if (g->verbose) { | 694 | if (g->verbose) { |
| 699 | ast_print(import_entry->root, 0); | 695 | ast_print(import_entry->root, 0); |
| 700 | |||
| 701 | fprintf(stderr, "\nSemantic Analysis:\n"); | ||
| 702 | fprintf(stderr, "--------------------\n"); | ||
| 703 | } | 696 | } |
| 704 | 697 | ||
| 705 | import_entry->path = source_path; | 698 | import_entry->path = source_path; |
| 706 | import_entry->di_file = LLVMZigCreateFile(g->dbuilder, buf_ptr(&basename), buf_ptr(&dirname)); | 699 | import_entry->di_file = LLVMZigCreateFile(g->dbuilder, buf_ptr(&basename), buf_ptr(&dirname)); |
| 707 | g->import_table.put(source_path, import_entry); | 700 | g->import_table.put(source_path, import_entry); |
| 708 | 701 | ||
| 709 | semantic_analyze(g, import_entry); | 702 | |
| 703 | assert(import_entry->root->type == NodeTypeRoot); | ||
| 704 | for (int decl_i = 0; decl_i < import_entry->root->data.root.top_level_decls.length; decl_i += 1) { | ||
| 705 | AstNode *top_level_decl = import_entry->root->data.root.top_level_decls.at(decl_i); | ||
| 706 | if (top_level_decl->type != NodeTypeUse) | ||
| 707 | continue; | ||
| 708 | |||
| 709 | auto entry = g->import_table.maybe_get(&top_level_decl->data.use.path); | ||
| 710 | if (!entry) { | ||
| 711 | Buf full_path = BUF_INIT; | ||
| 712 | os_path_join(g->root_source_dir, &top_level_decl->data.use.path, &full_path); | ||
| 713 | Buf import_code = BUF_INIT; | ||
| 714 | os_fetch_file_path(&full_path, &import_code); | ||
| 715 | codegen_add_code(g, &top_level_decl->data.use.path, &import_code); | ||
| 716 | } | ||
| 717 | } | ||
| 718 | } | ||
| 719 | |||
| 720 | void codegen_add_root_code(CodeGen *g, Buf *source_path, Buf *source_code) { | ||
| 721 | init(g, source_path); | ||
| 722 | |||
| 723 | codegen_add_code(g, source_path, source_code); | ||
| 724 | |||
| 725 | |||
| 726 | if (g->verbose) { | ||
| 727 | fprintf(stderr, "\nSemantic Analysis:\n"); | ||
| 728 | fprintf(stderr, "--------------------\n"); | ||
| 729 | } | ||
| 730 | semantic_analyze(g); | ||
| 710 | 731 | ||
| 711 | if (g->errors.length == 0) { | 732 | if (g->errors.length == 0) { |
| 712 | if (g->verbose) { | 733 | 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 { |