authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-10 01:25:20-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-10 01:25:20-07:00
log35b74d4013a81066cd45f4c99ec20907db310340
treece756e0719a57bd6808a86a67cc876f54f7ab8f6
parent49d0971cd4f6aa3f897a0f36272c05c641e25f79

order-independent declarations even from imports

closes #42

3 files changed, 100 insertions(+), 92 deletions(-)

src/analyze.cpp+93-92
...@@ -807,6 +807,20 @@ static void preview_fn_proto(CodeGen *g, ImportTableEntry *import,...@@ -807,6 +807,20 @@ static void preview_fn_proto(CodeGen *g, ImportTableEntry *import,
807 if (fn_def_node) {807 if (fn_def_node) {
808 preview_function_labels(g, fn_def_node->data.fn_def.body, fn_table_entry);808 preview_function_labels(g, fn_def_node->data.fn_def.body, fn_table_entry);
809 }809 }
810
811 if (is_pub && !struct_type) {
812 for (int i = 0; i < import->importers.length; i += 1) {
813 ImporterInfo importer = import->importers.at(i);
814 auto table_entry = importer.import->fn_table.maybe_get(proto_name);
815 if (table_entry) {
816 add_node_error(g, importer.source_node,
817 buf_sprintf("import of function '%s' overrides existing definition",
818 buf_ptr(proto_name)));
819 } else {
820 importer.import->fn_table.put(proto_name, fn_table_entry);
821 }
822 }
823 }
810}824}
811825
812static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode *node) {826static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode *node) {
...@@ -1715,6 +1729,23 @@ static VariableTableEntry *analyze_variable_declaration_raw(CodeGen *g, ImportTa...@@ -1715,6 +1729,23 @@ static VariableTableEntry *analyze_variable_declaration_raw(CodeGen *g, ImportTa
1715 variable_entry->is_ptr = true;1729 variable_entry->is_ptr = true;
1716 variable_entry->decl_node = source_node;1730 variable_entry->decl_node = source_node;
1717 context->variable_table.put(&variable_entry->name, variable_entry);1731 context->variable_table.put(&variable_entry->name, variable_entry);
1732
1733 bool is_pub = (variable_declaration->visib_mod != VisibModPrivate);
1734 if (is_pub) {
1735 for (int i = 0; i < import->importers.length; i += 1) {
1736 ImporterInfo importer = import->importers.at(i);
1737 auto table_entry = importer.import->block_context->variable_table.maybe_get(&variable_entry->name);
1738 if (table_entry) {
1739 add_node_error(g, importer.source_node,
1740 buf_sprintf("import of variable '%s' overrides existing definition",
1741 buf_ptr(&variable_entry->name)));
1742 } else {
1743 importer.import->block_context->variable_table.put(&variable_entry->name, variable_entry);
1744 }
1745 }
1746 }
1747
1748
1718 return variable_entry;1749 return variable_entry;
1719 }1750 }
1720 return nullptr;1751 return nullptr;
...@@ -2563,90 +2594,8 @@ static void analyze_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode...@@ -2563,90 +2594,8 @@ static void analyze_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode
2563 // already looked at these in the preview pass2594 // already looked at these in the preview pass
2564 break;2595 break;
2565 case NodeTypeUse:2596 case NodeTypeUse:
2566 {2597 // already took care of this
2567 for (int i = 0; i < node->data.use.directives->length; i += 1) {2598 break;
2568 AstNode *directive_node = node->data.use.directives->at(i);
2569 Buf *name = &directive_node->data.directive.name;
2570 add_node_error(g, directive_node,
2571 buf_sprintf("invalid directive: '%s'", buf_ptr(name)));
2572 }
2573
2574 ImportTableEntry *target_import = node->codegen_node->data.import_node.import;
2575 assert(target_import);
2576
2577 // import all the public functions
2578 {
2579 auto it = target_import->fn_table.entry_iterator();
2580 for (;;) {
2581 auto *entry = it.next();
2582 if (!entry)
2583 break;
2584
2585 FnTableEntry *fn_entry = entry->value;
2586 bool is_pub = (fn_entry->proto_node->data.fn_proto.visib_mod != VisibModPrivate);
2587 if (is_pub) {
2588 auto existing_entry = import->fn_table.maybe_get(entry->key);
2589 if (existing_entry) {
2590 add_node_error(g, node,
2591 buf_sprintf("import of function '%s' overrides existing definition",
2592 buf_ptr(&fn_entry->proto_node->data.fn_proto.name)));
2593 } else {
2594 import->fn_table.put(entry->key, entry->value);
2595 }
2596 }
2597 }
2598 }
2599
2600 // import all the public types
2601 {
2602 auto it = target_import->type_table.entry_iterator();
2603 for (;;) {
2604 auto *entry = it.next();
2605 if (!entry)
2606 break;
2607
2608 TypeTableEntry *type_entry = entry->value;
2609 if (type_entry->id == TypeTableEntryIdStruct) {
2610 AstNode *decl_node = type_entry->data.structure.decl_node;
2611 bool is_pub = (decl_node->data.struct_decl.visib_mod != VisibModPrivate);
2612 if (is_pub) {
2613 auto existing_entry = import->type_table.maybe_get(entry->key);
2614 if (existing_entry) {
2615 add_node_error(g, node,
2616 buf_sprintf("import of type '%s' overrides existing definition",
2617 buf_ptr(&type_entry->name)));
2618 } else {
2619 import->type_table.put(entry->key, entry->value);
2620 }
2621 }
2622 }
2623 }
2624 }
2625
2626 // import all the public variables
2627 {
2628 auto it = target_import->block_context->variable_table.entry_iterator();
2629 for (;;) {
2630 auto *entry = it.next();
2631 if (!entry)
2632 break;
2633
2634 VariableTableEntry *var = entry->value;
2635 bool is_pub = (var->decl_node->data.variable_declaration.visib_mod != VisibModPrivate);
2636 if (is_pub) {
2637 auto existing_entry = import->type_table.maybe_get(entry->key);
2638 if (existing_entry) {
2639 add_node_error(g, node,
2640 buf_sprintf("import of variable '%s' overrides existing definition",
2641 buf_ptr(&var->name)));
2642 } else {
2643 import->block_context->variable_table.put(entry->key, entry->value);
2644 }
2645 }
2646 }
2647 }
2648 break;
2649 }
2650 case NodeTypeStructDecl:2599 case NodeTypeStructDecl:
2651 {2600 {
2652 for (int i = 0; i < node->data.struct_decl.fns.length; i += 1) {2601 for (int i = 0; i < node->data.struct_decl.fns.length; i += 1) {
...@@ -2869,9 +2818,9 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast...@@ -2869,9 +2818,9 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast
2869 StructDeclNode *struct_codegen = &node->codegen_node->data.struct_decl_node;2818 StructDeclNode *struct_codegen = &node->codegen_node->data.struct_decl_node;
28702819
2871 Buf *name = &node->data.struct_decl.name;2820 Buf *name = &node->data.struct_decl.name;
2872 auto table_entry = import->type_table.maybe_get(name);2821 auto table_entry = g->primitive_type_table.maybe_get(name);
2873 if (!table_entry) {2822 if (!table_entry) {
2874 table_entry = g->primitive_type_table.maybe_get(name);2823 table_entry = import->type_table.maybe_get(name);
2875 }2824 }
2876 if (table_entry) {2825 if (table_entry) {
2877 struct_codegen->type_entry = table_entry->value;2826 struct_codegen->type_entry = table_entry->value;
...@@ -2890,6 +2839,21 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast...@@ -2890,6 +2839,21 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast
2890 // this type is incomplete until we do another pass2839 // this type is incomplete until we do another pass
2891 import->type_table.put(&entry->name, entry);2840 import->type_table.put(&entry->name, entry);
2892 struct_codegen->type_entry = entry;2841 struct_codegen->type_entry = entry;
2842
2843 bool is_pub = (node->data.struct_decl.visib_mod != VisibModPrivate);
2844 if (is_pub) {
2845 for (int i = 0; i < import->importers.length; i += 1) {
2846 ImporterInfo importer = import->importers.at(i);
2847 auto table_entry = importer.import->type_table.maybe_get(&entry->name);
2848 if (table_entry) {
2849 add_node_error(g, importer.source_node,
2850 buf_sprintf("import of type '%s' overrides existing definition",
2851 buf_ptr(&entry->name)));
2852 } else {
2853 importer.import->type_table.put(&entry->name, entry);
2854 }
2855 }
2856 }
2893 }2857 }
28942858
2895 // determine which other top level declarations this struct depends on.2859 // determine which other top level declarations this struct depends on.
...@@ -2977,7 +2941,7 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast...@@ -2977,7 +2941,7 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast
2977 resolve_top_level_decl(g, import, node);2941 resolve_top_level_decl(g, import, node);
2978 break;2942 break;
2979 case NodeTypeUse:2943 case NodeTypeUse:
2980 // nothing to do2944 // already taken care of
2981 break;2945 break;
2982 case NodeTypeDirective:2946 case NodeTypeDirective:
2983 case NodeTypeParamDecl:2947 case NodeTypeParamDecl:
...@@ -3054,11 +3018,6 @@ static void recursive_resolve_decl(CodeGen *g, ImportTableEntry *import, AstNode...@@ -3054,11 +3018,6 @@ static void recursive_resolve_decl(CodeGen *g, ImportTableEntry *import, AstNode
3054static void resolve_top_level_declarations_root(CodeGen *g, ImportTableEntry *import, AstNode *node) {3018static void resolve_top_level_declarations_root(CodeGen *g, ImportTableEntry *import, AstNode *node) {
3055 assert(node->type == NodeTypeRoot);3019 assert(node->type == NodeTypeRoot);
30563020
3057 for (int i = 0; i < node->data.root.top_level_decls.length; i += 1) {
3058 AstNode *child = node->data.root.top_level_decls.at(i);
3059 detect_top_level_decl_deps(g, import, child);
3060 }
3061
3062 while (g->unresolved_top_level_decls.size() > 0) {3021 while (g->unresolved_top_level_decls.size() > 0) {
3063 // for the sake of determinism, find the element with the lowest3022 // for the sake of determinism, find the element with the lowest
3064 // insert index and resolve that one.3023 // insert index and resolve that one.
...@@ -3095,6 +3054,48 @@ static void analyze_top_level_decls_root(CodeGen *g, ImportTableEntry *import, A...@@ -3095,6 +3054,48 @@ static void analyze_top_level_decls_root(CodeGen *g, ImportTableEntry *import, A
3095}3054}
30963055
3097void semantic_analyze(CodeGen *g) {3056void semantic_analyze(CodeGen *g) {
3057 {
3058 auto it = g->import_table.entry_iterator();
3059 for (;;) {
3060 auto *entry = it.next();
3061 if (!entry)
3062 break;
3063
3064 ImportTableEntry *import = entry->value;
3065
3066 for (int i = 0; i < import->root->data.root.top_level_decls.length; i += 1) {
3067 AstNode *child = import->root->data.root.top_level_decls.at(i);
3068 if (child->type == NodeTypeUse) {
3069 for (int i = 0; i < child->data.use.directives->length; i += 1) {
3070 AstNode *directive_node = child->data.use.directives->at(i);
3071 Buf *name = &directive_node->data.directive.name;
3072 add_node_error(g, directive_node,
3073 buf_sprintf("invalid directive: '%s'", buf_ptr(name)));
3074 }
3075
3076 ImportTableEntry *target_import = child->codegen_node->data.import_node.import;
3077 assert(target_import);
3078
3079 target_import->importers.append({import, child});
3080 }
3081 }
3082 }
3083 }
3084 {
3085 auto it = g->import_table.entry_iterator();
3086 for (;;) {
3087 auto *entry = it.next();
3088 if (!entry)
3089 break;
3090
3091 ImportTableEntry *import = entry->value;
3092
3093 for (int i = 0; i < import->root->data.root.top_level_decls.length; i += 1) {
3094 AstNode *child = import->root->data.root.top_level_decls.at(i);
3095 detect_top_level_decl_deps(g, import, child);
3096 }
3097 }
3098 }
3098 {3099 {
3099 auto it = g->import_table.entry_iterator();3100 auto it = g->import_table.entry_iterator();
3100 for (;;) {3101 for (;;) {
src/analyze.hpp+6
...@@ -105,6 +105,11 @@ struct TypeTableEntry {...@@ -105,6 +105,11 @@ struct TypeTableEntry {
105105
106};106};
107107
108struct ImporterInfo {
109 ImportTableEntry *import;
110 AstNode *source_node;
111};
112
108struct ImportTableEntry {113struct ImportTableEntry {
109 AstNode *root;114 AstNode *root;
110 Buf *path; // relative to root_source_dir115 Buf *path; // relative to root_source_dir
...@@ -112,6 +117,7 @@ struct ImportTableEntry {...@@ -112,6 +117,7 @@ struct ImportTableEntry {
112 Buf *source_code;117 Buf *source_code;
113 ZigList<int> *line_offsets;118 ZigList<int> *line_offsets;
114 BlockContext *block_context;119 BlockContext *block_context;
120 ZigList<ImporterInfo> importers;
115121
116 // reminder: hash tables must be initialized before use122 // reminder: hash tables must be initialized before use
117 HashMap<Buf *, FnTableEntry *, buf_hash, buf_eql_buf> fn_table;123 HashMap<Buf *, FnTableEntry *, buf_hash, buf_eql_buf> fn_table;
test/run_tests.cpp+1
...@@ -994,6 +994,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {...@@ -994,6 +994,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
994994
995 add_simple_case("order-independent declarations", R"SOURCE(995 add_simple_case("order-independent declarations", R"SOURCE(
996use "std.zig";996use "std.zig";
997const z : #typeof(stdin_fileno) = 0;
997const x : #typeof(y) = 1234;998const x : #typeof(y) = 1234;
998const y : u16 = 5678;999const y : u16 = 5678;
999pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {1000pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {